ingestr 0.13.92__py3-none-any.whl → 0.13.94__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 ingestr might be problematic. Click here for more details.

@@ -870,123 +870,77 @@ class MongoDbCollectionResourceConfiguration(BaseConfiguration):
870
870
  def convert_mongo_shell_to_extended_json(query_string: str) -> str:
871
871
  """
872
872
  Convert MongoDB shell syntax to MongoDB Extended JSON v2 format.
873
-
873
+
874
874
  This function handles common MongoDB shell constructs like ISODate, ObjectId,
875
875
  NumberLong, NumberDecimal, etc. and converts them to their Extended JSON equivalents
876
876
  that can be parsed by bson.json_util.
877
-
877
+
878
878
  Args:
879
879
  query_string: A string containing MongoDB shell syntax
880
-
880
+
881
881
  Returns:
882
882
  A string with MongoDB Extended JSON v2 format
883
-
883
+
884
884
  Examples:
885
885
  >>> convert_mongo_shell_to_extended_json('ISODate("2010-01-01T00:00:00.000Z")')
886
886
  '{"$date": "2010-01-01T00:00:00.000Z"}'
887
-
887
+
888
888
  >>> convert_mongo_shell_to_extended_json('ObjectId("507f1f77bcf86cd799439011")')
889
889
  '{"$oid": "507f1f77bcf86cd799439011"}'
890
890
  """
891
891
  converted = query_string
892
-
892
+
893
893
  # Convert ISODate("...") to {"$date": "..."}
894
894
  # Pattern matches ISODate("2010-01-01T00:00:00.000+0000") or similar
895
- converted = re.sub(
896
- r'ISODate\("([^"]+)"\)',
897
- r'{"$date": "\1"}',
898
- converted
899
- )
900
-
895
+ converted = re.sub(r'ISODate\("([^"]+)"\)', r'{"$date": "\1"}', converted)
896
+
901
897
  # Convert ObjectId("...") to {"$oid": "..."}
902
- converted = re.sub(
903
- r'ObjectId\("([^"]+)"\)',
904
- r'{"$oid": "\1"}',
905
- converted
906
- )
907
-
898
+ converted = re.sub(r'ObjectId\("([^"]+)"\)', r'{"$oid": "\1"}', converted)
899
+
908
900
  # Convert NumberLong(...) to {"$numberLong": "..."}
909
901
  # Note: NumberLong can have quotes or not: NumberLong(123) or NumberLong("123")
910
- converted = re.sub(
911
- r'NumberLong\("([^"]+)"\)',
912
- r'{"$numberLong": "\1"}',
913
- converted
914
- )
915
- converted = re.sub(
916
- r'NumberLong\(([^)]+)\)',
917
- r'{"$numberLong": "\1"}',
918
- converted
919
- )
920
-
902
+ converted = re.sub(r'NumberLong\("([^"]+)"\)', r'{"$numberLong": "\1"}', converted)
903
+ converted = re.sub(r"NumberLong\(([^)]+)\)", r'{"$numberLong": "\1"}', converted)
904
+
921
905
  # Convert NumberInt(...) to {"$numberInt": "..."}
922
- converted = re.sub(
923
- r'NumberInt\("([^"]+)"\)',
924
- r'{"$numberInt": "\1"}',
925
- converted
926
- )
927
- converted = re.sub(
928
- r'NumberInt\(([^)]+)\)',
929
- r'{"$numberInt": "\1"}',
930
- converted
931
- )
932
-
906
+ converted = re.sub(r'NumberInt\("([^"]+)"\)', r'{"$numberInt": "\1"}', converted)
907
+ converted = re.sub(r"NumberInt\(([^)]+)\)", r'{"$numberInt": "\1"}', converted)
908
+
933
909
  # Convert NumberDecimal("...") to {"$numberDecimal": "..."}
934
910
  converted = re.sub(
935
- r'NumberDecimal\("([^"]+)"\)',
936
- r'{"$numberDecimal": "\1"}',
937
- converted
911
+ r'NumberDecimal\("([^"]+)"\)', r'{"$numberDecimal": "\1"}', converted
938
912
  )
939
-
913
+
940
914
  # Convert Timestamp(..., ...) to {"$timestamp": {"t": ..., "i": ...}}
941
915
  # Timestamp(1234567890, 1) -> {"$timestamp": {"t": 1234567890, "i": 1}}
942
916
  converted = re.sub(
943
- r'Timestamp\((\d+),\s*(\d+)\)',
944
- r'{"$timestamp": {"t": \1, "i": \2}}',
945
- converted
917
+ r"Timestamp\((\d+),\s*(\d+)\)", r'{"$timestamp": {"t": \1, "i": \2}}', converted
946
918
  )
947
-
919
+
948
920
  # Convert BinData(..., "...") to {"$binary": {"base64": "...", "subType": "..."}}
949
921
  converted = re.sub(
950
922
  r'BinData\((\d+),\s*"([^"]+)"\)',
951
923
  r'{"$binary": {"base64": "\2", "subType": "\1"}}',
952
- converted
924
+ converted,
953
925
  )
954
-
926
+
955
927
  # Convert MinKey() to {"$minKey": 1}
956
- converted = re.sub(
957
- r'MinKey\(\)',
958
- r'{"$minKey": 1}',
959
- converted
960
- )
961
-
928
+ converted = re.sub(r"MinKey\(\)", r'{"$minKey": 1}', converted)
929
+
962
930
  # Convert MaxKey() to {"$maxKey": 1}
963
- converted = re.sub(
964
- r'MaxKey\(\)',
965
- r'{"$maxKey": 1}',
966
- converted
967
- )
968
-
931
+ converted = re.sub(r"MaxKey\(\)", r'{"$maxKey": 1}', converted)
932
+
969
933
  # Convert UUID("...") to {"$uuid": "..."}
970
- converted = re.sub(
971
- r'UUID\("([^"]+)"\)',
972
- r'{"$uuid": "\1"}',
973
- converted
974
- )
975
-
934
+ converted = re.sub(r'UUID\("([^"]+)"\)', r'{"$uuid": "\1"}', converted)
935
+
976
936
  # Convert DBRef("collection", "id") to {"$ref": "collection", "$id": "id"}
977
937
  converted = re.sub(
978
- r'DBRef\("([^"]+)",\s*"([^"]+)"\)',
979
- r'{"$ref": "\1", "$id": "\2"}',
980
- converted
938
+ r'DBRef\("([^"]+)",\s*"([^"]+)"\)', r'{"$ref": "\1", "$id": "\2"}', converted
981
939
  )
982
-
940
+
983
941
  # Convert Code("...") to {"$code": "..."}
984
- converted = re.sub(
985
- r'Code\("([^"]+)"\)',
986
- r'{"$code": "\1"}',
987
- converted
988
- )
989
-
942
+ converted = re.sub(r'Code\("([^"]+)"\)', r'{"$code": "\1"}', converted)
943
+
990
944
  return converted
991
945
 
992
946
 
ingestr/src/sources.py CHANGED
@@ -430,16 +430,17 @@ class MongoDbSource:
430
430
  # Parse the query using MongoDB's extended JSON parser
431
431
  # First, convert MongoDB shell syntax to Extended JSON format
432
432
  from bson import json_util
433
+
433
434
  from ingestr.src.mongodb.helpers import convert_mongo_shell_to_extended_json
434
-
435
+
435
436
  # Convert MongoDB shell constructs to Extended JSON v2 format
436
437
  converted_query = convert_mongo_shell_to_extended_json(query_json)
437
-
438
+
438
439
  try:
439
440
  query = json_util.loads(converted_query)
440
441
  except Exception as e:
441
442
  raise ValueError(f"Invalid MongoDB query format: {e}")
442
-
443
+
443
444
  # Validate that it's a list for aggregation pipeline
444
445
  if not isinstance(query, list):
445
446
  raise ValueError(
@@ -1883,6 +1884,72 @@ class DynamoDBSource:
1883
1884
  return dynamodb(table, creds, incremental)
1884
1885
 
1885
1886
 
1887
+ class DoceboSource:
1888
+ def handles_incrementality(self) -> bool:
1889
+ return False
1890
+
1891
+ def dlt_source(self, uri: str, table: str, **kwargs):
1892
+ # docebo://?base_url=https://yourcompany.docebosaas.com&client_id=xxx&client_secret=xxx
1893
+ # Optional: &username=xxx&password=xxx for password grant type
1894
+
1895
+ if kwargs.get("incremental_key"):
1896
+ raise ValueError("Incremental loads are not yet supported for Docebo")
1897
+
1898
+ parsed_uri = urlparse(uri)
1899
+ source_params = parse_qs(parsed_uri.query)
1900
+
1901
+ base_url = source_params.get("base_url")
1902
+ if not base_url:
1903
+ raise ValueError("base_url is required to connect to Docebo")
1904
+
1905
+ client_id = source_params.get("client_id")
1906
+ if not client_id:
1907
+ raise ValueError("client_id is required to connect to Docebo")
1908
+
1909
+ client_secret = source_params.get("client_secret")
1910
+ if not client_secret:
1911
+ raise ValueError("client_secret is required to connect to Docebo")
1912
+
1913
+ # Username and password are optional (uses client_credentials grant if not provided)
1914
+ username = source_params.get("username", [None])[0]
1915
+ password = source_params.get("password", [None])[0]
1916
+
1917
+ # Supported tables
1918
+ supported_tables = [
1919
+ "users",
1920
+ "courses",
1921
+ "user_fields",
1922
+ "branches",
1923
+ "groups",
1924
+ "group_members",
1925
+ "course_fields",
1926
+ "learning_objects",
1927
+ "learning_plans",
1928
+ "learning_plan_enrollments",
1929
+ "learning_plan_course_enrollments",
1930
+ "course_enrollments",
1931
+ "sessions",
1932
+ "categories",
1933
+ "certifications",
1934
+ "external_training",
1935
+ "survey_answers",
1936
+ ]
1937
+ if table not in supported_tables:
1938
+ raise ValueError(
1939
+ f"Resource '{table}' is not supported for Docebo source. Supported tables: {', '.join(supported_tables)}"
1940
+ )
1941
+
1942
+ from ingestr.src.docebo import docebo_source
1943
+
1944
+ return docebo_source(
1945
+ base_url=base_url[0],
1946
+ client_id=client_id[0],
1947
+ client_secret=client_secret[0],
1948
+ username=username,
1949
+ password=password,
1950
+ ).with_resources(table)
1951
+
1952
+
1886
1953
  class GoogleAnalyticsSource:
1887
1954
  def handles_incrementality(self) -> bool:
1888
1955
  return True
@@ -2537,7 +2604,7 @@ class SalesforceSource:
2537
2604
 
2538
2605
  if table not in src.resources:
2539
2606
  raise UnsupportedResourceError(table, "Salesforce")
2540
-
2607
+
2541
2608
  return src.with_resources(table)
2542
2609
 
2543
2610
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ingestr
3
- Version: 0.13.92
3
+ Version: 0.13.94
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
@@ -47,7 +47,7 @@ Requires-Dist: databricks-sqlalchemy==1.0.2
47
47
  Requires-Dist: dataclasses-json==0.6.7
48
48
  Requires-Dist: decorator==5.2.1
49
49
  Requires-Dist: deprecation==2.1.0
50
- Requires-Dist: dlt-cratedb==0.0.1
50
+ Requires-Dist: dlt-cratedb==0.0.2
51
51
  Requires-Dist: dlt==1.11.0
52
52
  Requires-Dist: dnspython==2.7.0
53
53
  Requires-Dist: duckdb-engine==0.17.0
@@ -2,24 +2,24 @@ ingestr/conftest.py,sha256=OE2yxeTCosS9CUFVuqNypm-2ftYvVBeeq7egm3878cI,1981
2
2
  ingestr/main.py,sha256=qo0g3wCFl8a_1jUwXagX8L1Q8PKKQlTF7md9pfnzW0Y,27155
3
3
  ingestr/src/.gitignore,sha256=8cX1AZTSI0TcdZFGTmS_oyBjpfCzhOEt0DdAo2dFIY8,203
4
4
  ingestr/src/blob.py,sha256=UUWMjHUuoR9xP1XZQ6UANQmnMVyDx3d0X4-2FQC271I,2138
5
- ingestr/src/buildinfo.py,sha256=bR_SHBOnG2JaQD4K3ZvZC_ctkUAC7obqll7Reuy7YHE,21
6
- ingestr/src/destinations.py,sha256=QNT2rm91cZmY1_Zyj4VnbI14qGmZOUQOQUg9xUTVVYs,23799
5
+ ingestr/src/buildinfo.py,sha256=tjPoi11Dio9bwbPoZ9l6d066j_pVtEhVxjcmSoQLbz0,21
6
+ ingestr/src/destinations.py,sha256=UvZKKp1HUWR8Vxd89qOZcOVqOmlMnIIe5c8EByKylN0,23755
7
7
  ingestr/src/errors.py,sha256=Ufs4_DfE77_E3vnA1fOQdi6cmuLVNm7_SbFLkL1XPGk,686
8
- ingestr/src/factory.py,sha256=hC5E_XgrgTHMqwqPc6ihUYvRGTGMTzdPfQhrgPyD0tY,6945
8
+ ingestr/src/factory.py,sha256=DQ3DsaFDqEVB8yNoQnQf451BRuVOuDmtpqzkUHra4Iw,6995
9
9
  ingestr/src/filters.py,sha256=0n0sNAVG_f-B_1r7lW5iNtw9z_G1bxWzPaiL1i6tnbU,1665
10
10
  ingestr/src/http_client.py,sha256=bxqsk6nJNXCo-79gW04B53DQO-yr25vaSsqP0AKtjx4,732
11
11
  ingestr/src/loader.py,sha256=9NaWAyfkXdqAZSS-N72Iwo36Lbx4PyqIfaaH1dNdkFs,1712
12
12
  ingestr/src/masking.py,sha256=VN0LdfvExhQ1bZMRylGtaBUIoH-vjuIUmRnYKwo3yiY,11358
13
13
  ingestr/src/partition.py,sha256=BrIP6wFJvyR7Nus_3ElnfxknUXeCipK_E_bB8kZowfc,969
14
14
  ingestr/src/resource.py,sha256=ZqmZxFQVGlF8rFPhBiUB08HES0yoTj8sZ--jKfaaVps,1164
15
- ingestr/src/sources.py,sha256=5S-RDTrAD6ZfpzTC4m7RW3WPKY2gBWCrPRC9esEsO5U,125785
15
+ ingestr/src/sources.py,sha256=A049YPuofkFHQGrDVMtxRpvaU1GyKlA_KkmXwTzIrE4,128026
16
16
  ingestr/src/table_definition.py,sha256=REbAbqdlmUMUuRh8nEQRreWjPVOQ5ZcfqGkScKdCrmk,390
17
17
  ingestr/src/time.py,sha256=H_Fk2J4ShXyUM-EMY7MqCLZQhlnZMZvO952bmZPc4yE,254
18
18
  ingestr/src/version.py,sha256=J_2xgZ0mKlvuHcjdKCx2nlioneLH0I47JiU_Slr_Nwc,189
19
19
  ingestr/src/adjust/__init__.py,sha256=ULjtJqrNS6XDvUyGl0tjl12-tLyXlCgeFe2icTbtu3Q,3255
20
20
  ingestr/src/adjust/adjust_helpers.py,sha256=IHSS94A7enOWkZ8cP5iW3RdYt0Xl3qZGAmDc1Xy4qkI,3802
21
21
  ingestr/src/airtable/__init__.py,sha256=XzRsS39xszUlh_s7P1_zq5v8vLfjz3m-NtTPaa8TTZU,2818
22
- ingestr/src/applovin/__init__.py,sha256=Y02ysL2vRiDoP3uN9ven2OVcH9zTd8PbmIjqIHds4zU,6985
22
+ ingestr/src/applovin/__init__.py,sha256=X_YCLppPrnL8KXfYWICE_uDfMzHHH3JZ-DBGZ1RlaOI,6984
23
23
  ingestr/src/applovin_max/__init__.py,sha256=fxXqsIibJarp5NOGe08G964HftwLDymTtYS_LqPJht4,3315
24
24
  ingestr/src/appsflyer/__init__.py,sha256=QoK-B3cYYMD3bqzQaLWNH6FkJyjRbzRkBF2n6urxubs,8071
25
25
  ingestr/src/appsflyer/client.py,sha256=E6xPW4KlbBnQZ0K4eq2Xgb3AmGrtrzIX9bX8EnQr-D4,3615
@@ -40,9 +40,12 @@ ingestr/src/chess/settings.py,sha256=p0RlCGgtXUacPDEvZmwzSWmzX0Apj1riwfz-nrMK89k
40
40
  ingestr/src/clickup/__init__.py,sha256=uvfAqNturT4bMvU4NS3E8BdL6nvDFzNuh7bMlih8HJk,2547
41
41
  ingestr/src/clickup/helpers.py,sha256=RzDKMUAHccuDhocIQ2ToBXfCERo8CBJqA3t-IPltBCE,1519
42
42
  ingestr/src/collector/spinner.py,sha256=_ZUqF5MI43hVIULdjF5s5mrAZbhEFXaiWirQmrv3Yk4,1201
43
+ ingestr/src/docebo/__init__.py,sha256=NGfXafjuO9lDqBF7su71JaCKayhKTRmqL-hV9RlWZbQ,28346
44
+ ingestr/src/docebo/client.py,sha256=nki0kNQhN8VDz5cdqlQQPhr1JMPlcNEYKnWK3umAyOc,15663
45
+ ingestr/src/docebo/helpers.py,sha256=SaEjta6k3Lj-S5fvrheA5_xj7zfASMdOc_ihsqno5ko,3238
43
46
  ingestr/src/dynamodb/__init__.py,sha256=swhxkeYBbJ35jn1IghCtvYWT2BM33KynVCh_oR4z28A,2264
44
47
  ingestr/src/elasticsearch/__init__.py,sha256=m-q93HgUmTwGDUwHOjHawstWL06TC3WIX3H05szybrY,2556
45
- ingestr/src/facebook_ads/__init__.py,sha256=15GiovITANe0al5MI6WWLdl3LDmdBd1YpkUWBV3g6bk,9715
48
+ ingestr/src/facebook_ads/__init__.py,sha256=6kiU_t_rt9uedGBLEjYFrfAnNQiYSFiUePRqPA3OloQ,9827
46
49
  ingestr/src/facebook_ads/exceptions.py,sha256=4Nlbc0Mv3i5g-9AoyT-n1PIa8IDi3VCTfEAzholx4Wc,115
47
50
  ingestr/src/facebook_ads/helpers.py,sha256=c-WG008yU_zIdhFwljtqE2jfjVYuaVoNKldxcnJN3U4,9761
48
51
  ingestr/src/facebook_ads/settings.py,sha256=Bsic8RcmH-NfEZ7r_NGospTCmwISK9XaMT5y2NZirtg,4938
@@ -50,7 +53,7 @@ ingestr/src/facebook_ads/utils.py,sha256=ES2ylPoW3j3fjp6OMUgp21n1cG1OktXsmWWMk5v
50
53
  ingestr/src/filesystem/__init__.py,sha256=42YAOHQxZ7TkTXC1eeaLUJpjqJ3l7DH7C8j927pV4pc,4353
51
54
  ingestr/src/filesystem/helpers.py,sha256=bg0muSHZr3hMa8H4jN2-LGWzI-SUoKlQNiWJ74-YYms,3211
52
55
  ingestr/src/filesystem/readers.py,sha256=a0fKkaRpnAOGsXI3EBNYZa7x6tlmAOsgRzb883StY30,3987
53
- ingestr/src/fluxx/__init__.py,sha256=Ei8BE0KAEzpadJT9RO5-8zMA7LvnIPhNPDKF4EyBcLo,328980
56
+ ingestr/src/fluxx/__init__.py,sha256=1BLBHkIK0vlTtFYoc_8Uf2M4R7VphxYBinoiYgmpfg8,601058
54
57
  ingestr/src/fluxx/helpers.py,sha256=dCNgvMMTSEO4LNp6luNZ-XrV4NPW-_OUfmp0k3jFhuc,6602
55
58
  ingestr/src/frankfurter/__init__.py,sha256=aeyiv1jwcwblV5OeqG81vFcJo_Wc1bUlDwzdE4gnQiw,5246
56
59
  ingestr/src/frankfurter/helpers.py,sha256=SpRr992OcSf7IDI5y-ToUdO6m6sGpqFz59LTY0ojchI,1502
@@ -96,7 +99,7 @@ ingestr/src/linkedin_ads/helpers.py,sha256=eUWudRVlXl4kqIhfXQ1eVsUpZwJn7UFqKSpnb
96
99
  ingestr/src/mixpanel/__init__.py,sha256=s1QtqMP0BTGW6YtdCabJFWj7lEn7KujzELwGpBOQgfs,1796
97
100
  ingestr/src/mixpanel/client.py,sha256=c_reouegOVYBOwHLfgYFwpmkba0Sxro1Zkml07NCYf0,3602
98
101
  ingestr/src/mongodb/__init__.py,sha256=wu3KJ3VH5FF67gctJqm4T3ZTdBOQam1u6xuFBohq7bs,7486
99
- ingestr/src/mongodb/helpers.py,sha256=-CZo96tRPy5SvJVMejJ1F72F-PJhyVJ3Rfpk0o2M9rQ,35243
102
+ ingestr/src/mongodb/helpers.py,sha256=6uRgxXgSHh38SApuZU7DyIw2Bvs9NVOc-VtI1wmOItE,34812
100
103
  ingestr/src/notion/__init__.py,sha256=36wUui8finbc85ObkRMq8boMraXMUehdABN_AMe_hzA,1834
101
104
  ingestr/src/notion/settings.py,sha256=MwQVZViJtnvOegfjXYc_pJ50oUYgSRPgwqu7TvpeMOA,82
102
105
  ingestr/src/notion/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -158,8 +161,8 @@ ingestr/testdata/merge_expected.csv,sha256=DReHqWGnQMsf2PBv_Q2pfjsgvikYFnf1zYcQZ
158
161
  ingestr/testdata/merge_part1.csv,sha256=Pw8Z9IDKcNU0qQHx1z6BUf4rF_-SxKGFOvymCt4OY9I,185
159
162
  ingestr/testdata/merge_part2.csv,sha256=T_GiWxA81SN63_tMOIuemcvboEFeAmbKc7xRXvL9esw,287
160
163
  ingestr/tests/unit/test_smartsheets.py,sha256=djU1TFD0-Zr7h-WNhm281DoyGApOpNOrZcN4r-U9Pks,4873
161
- ingestr-0.13.92.dist-info/METADATA,sha256=m59fSWl6js1EilscWOHeNyTe1p7mfKor2Xc2qvElXwA,15182
162
- ingestr-0.13.92.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
163
- ingestr-0.13.92.dist-info/entry_points.txt,sha256=oPJy0KBnPWYjDtP1k8qwAihcTLHSZokSQvRAw_wtfJM,46
164
- ingestr-0.13.92.dist-info/licenses/LICENSE.md,sha256=cW8wIhn8HFE-KLStDF9jHQ1O_ARWP3kTpk_-eOccL24,1075
165
- ingestr-0.13.92.dist-info/RECORD,,
164
+ ingestr-0.13.94.dist-info/METADATA,sha256=8HZLFO-404rkW6UylsNKFWgdPGBWlzXp50UDwgcdMR8,15182
165
+ ingestr-0.13.94.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
166
+ ingestr-0.13.94.dist-info/entry_points.txt,sha256=oPJy0KBnPWYjDtP1k8qwAihcTLHSZokSQvRAw_wtfJM,46
167
+ ingestr-0.13.94.dist-info/licenses/LICENSE.md,sha256=cW8wIhn8HFE-KLStDF9jHQ1O_ARWP3kTpk_-eOccL24,1075
168
+ ingestr-0.13.94.dist-info/RECORD,,