ingestr 0.13.49__py3-none-any.whl → 0.13.51__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.
- ingestr/src/buildinfo.py +1 -1
- ingestr/src/factory.py +2 -0
- ingestr/src/http_client.py +14 -8
- ingestr/src/solidgate/__init__.py +31 -1
- ingestr/src/solidgate/helpers.py +66 -1
- ingestr/src/stripe_analytics/settings.py +55 -8
- {ingestr-0.13.49.dist-info → ingestr-0.13.51.dist-info}/METADATA +1 -1
- {ingestr-0.13.49.dist-info → ingestr-0.13.51.dist-info}/RECORD +11 -11
- {ingestr-0.13.49.dist-info → ingestr-0.13.51.dist-info}/WHEEL +0 -0
- {ingestr-0.13.49.dist-info → ingestr-0.13.51.dist-info}/entry_points.txt +0 -0
- {ingestr-0.13.49.dist-info → ingestr-0.13.51.dist-info}/licenses/LICENSE.md +0 -0
ingestr/src/buildinfo.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = "v0.13.
|
|
1
|
+
version = "v0.13.51"
|
ingestr/src/factory.py
CHANGED
|
@@ -59,6 +59,7 @@ from ingestr.src.sources import (
|
|
|
59
59
|
StripeAnalyticsSource,
|
|
60
60
|
TikTokSource,
|
|
61
61
|
ZendeskSource,
|
|
62
|
+
SmartsheetSource,
|
|
62
63
|
)
|
|
63
64
|
|
|
64
65
|
SQL_SOURCE_SCHEMES = [
|
|
@@ -161,6 +162,7 @@ class SourceDestinationFactory:
|
|
|
161
162
|
"elasticsearch": ElasticsearchSource,
|
|
162
163
|
"attio": AttioSource,
|
|
163
164
|
"solidgate": SolidgateSource,
|
|
165
|
+
"smartsheet": SmartsheetSource,
|
|
164
166
|
}
|
|
165
167
|
destinations: Dict[str, Type[DestinationProtocol]] = {
|
|
166
168
|
"bigquery": BigQueryDestination,
|
ingestr/src/http_client.py
CHANGED
|
@@ -2,17 +2,23 @@ import requests
|
|
|
2
2
|
from dlt.sources.helpers.requests import Client
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
def create_client() -> requests.Session:
|
|
5
|
+
def create_client(retry_status_codes: list[int] | None = None) -> requests.Session:
|
|
6
|
+
if retry_status_codes is None:
|
|
7
|
+
retry_status_codes = [502]
|
|
6
8
|
return Client(
|
|
7
9
|
raise_for_status=False,
|
|
8
|
-
retry_condition=
|
|
10
|
+
retry_condition=retry_on_status_code(retry_status_codes),
|
|
9
11
|
request_max_attempts=12,
|
|
12
|
+
request_backoff_factor=10,
|
|
10
13
|
).session
|
|
11
14
|
|
|
12
15
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
def retry_on_status_code(retry_status_codes: list[int]):
|
|
17
|
+
def retry_on_limit(
|
|
18
|
+
response: requests.Response | None, exception: BaseException | None
|
|
19
|
+
) -> bool:
|
|
20
|
+
if response is None:
|
|
21
|
+
return False
|
|
22
|
+
return response.status_code in retry_status_codes
|
|
23
|
+
|
|
24
|
+
return retry_on_limit
|
|
@@ -94,4 +94,34 @@ def solidgate_source(
|
|
|
94
94
|
start_dt = dateTime.last_value
|
|
95
95
|
yield solidgate_client.fetch_data(path, date_from=start_dt, date_to=end_dt)
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
@dlt.resource(
|
|
98
|
+
name="financial-entries",
|
|
99
|
+
write_disposition="merge",
|
|
100
|
+
primary_key="id",
|
|
101
|
+
columns={
|
|
102
|
+
"created_at": {"data_type": "timestamp", "partition": True},
|
|
103
|
+
},
|
|
104
|
+
)
|
|
105
|
+
def fetch_financial_entries(
|
|
106
|
+
dateTime=dlt.sources.incremental(
|
|
107
|
+
"created_at",
|
|
108
|
+
initial_value=start_date,
|
|
109
|
+
end_value=end_date,
|
|
110
|
+
range_start="closed",
|
|
111
|
+
range_end="closed",
|
|
112
|
+
),
|
|
113
|
+
):
|
|
114
|
+
if dateTime.end_value is None:
|
|
115
|
+
end_date = pendulum.now(tz="UTC")
|
|
116
|
+
else:
|
|
117
|
+
end_date = dateTime.end_value
|
|
118
|
+
|
|
119
|
+
start_date = dateTime.last_value
|
|
120
|
+
yield solidgate_client.fetch_financial_entry_data(start_date, end_date)
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
fetch_all_subscriptions,
|
|
124
|
+
fetch_apm_orders,
|
|
125
|
+
fetch_card_orders,
|
|
126
|
+
fetch_financial_entries,
|
|
127
|
+
)
|
ingestr/src/solidgate/helpers.py
CHANGED
|
@@ -2,7 +2,10 @@ import base64
|
|
|
2
2
|
import hashlib
|
|
3
3
|
import hmac
|
|
4
4
|
import json
|
|
5
|
+
import time
|
|
6
|
+
from io import StringIO
|
|
5
7
|
|
|
8
|
+
import pandas as pd # type: ignore
|
|
6
9
|
import pendulum
|
|
7
10
|
|
|
8
11
|
from ingestr.src.http_client import create_client
|
|
@@ -13,7 +16,7 @@ class SolidgateClient:
|
|
|
13
16
|
self.base_url = "https://reports.solidgate.com/api/v1"
|
|
14
17
|
self.public_key = public_key
|
|
15
18
|
self.secret_key = secret_key
|
|
16
|
-
self.client = create_client()
|
|
19
|
+
self.client = create_client(retry_status_codes=[204])
|
|
17
20
|
|
|
18
21
|
def fetch_data(
|
|
19
22
|
self,
|
|
@@ -66,6 +69,68 @@ class SolidgateClient:
|
|
|
66
69
|
if not next_page_iterator or next_page_iterator == "None":
|
|
67
70
|
break
|
|
68
71
|
|
|
72
|
+
def fetch_financial_entry_data(
|
|
73
|
+
self, date_from: pendulum.DateTime, date_to: pendulum.DateTime
|
|
74
|
+
):
|
|
75
|
+
request_payload = {
|
|
76
|
+
"date_from": date_from.format("YYYY-MM-DD HH:mm:ss"),
|
|
77
|
+
"date_to": date_to.format("YYYY-MM-DD HH:mm:ss"),
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
json_string = json.dumps(request_payload)
|
|
81
|
+
signature = self.generateSignature(json_string)
|
|
82
|
+
headers = {
|
|
83
|
+
"merchant": self.public_key,
|
|
84
|
+
"Signature": signature,
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
url = f"{self.base_url}/finance/financial_entries"
|
|
89
|
+
post_response = self.client.post(url, headers=headers, json=request_payload)
|
|
90
|
+
post_response.raise_for_status()
|
|
91
|
+
report_url = post_response.json().get("report_url")
|
|
92
|
+
if not report_url:
|
|
93
|
+
return f"Report URL not found in the response: {post_response.json()}", 400
|
|
94
|
+
|
|
95
|
+
# Wait for 5 seconds before attempting to download the report as report may not be immediately available
|
|
96
|
+
time.sleep(5)
|
|
97
|
+
|
|
98
|
+
data = self.public_key + self.public_key
|
|
99
|
+
hmac_hash = hmac.new(
|
|
100
|
+
self.secret_key.encode("utf-8"), data.encode("utf-8"), hashlib.sha512
|
|
101
|
+
).digest()
|
|
102
|
+
signature_get = base64.b64encode(hmac_hash.hex().encode("utf-8")).decode(
|
|
103
|
+
"utf-8"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
headers_get = {
|
|
107
|
+
"merchant": self.public_key,
|
|
108
|
+
"Signature": signature_get,
|
|
109
|
+
"Content-Type": "application/json",
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
get_response = self.client.get(report_url, headers=headers_get)
|
|
113
|
+
|
|
114
|
+
if get_response.status_code == 200:
|
|
115
|
+
try:
|
|
116
|
+
response_json = json.loads(get_response.content)
|
|
117
|
+
if "error" in response_json:
|
|
118
|
+
raise Exception(f"API Error: {response_json['error']['messages']}")
|
|
119
|
+
except json.JSONDecodeError:
|
|
120
|
+
try:
|
|
121
|
+
csv_data = get_response.content.decode("utf-8")
|
|
122
|
+
df = pd.read_csv(StringIO(csv_data))
|
|
123
|
+
df["created_at"] = df["created_at"].apply(
|
|
124
|
+
lambda x: pendulum.parse(x)
|
|
125
|
+
)
|
|
126
|
+
return df
|
|
127
|
+
except Exception as e:
|
|
128
|
+
raise Exception(f"Error reading CSV: {e}")
|
|
129
|
+
else:
|
|
130
|
+
raise Exception(
|
|
131
|
+
f"Failed to get report. Status code: {get_response.status_code}"
|
|
132
|
+
)
|
|
133
|
+
|
|
69
134
|
def generateSignature(self, json_string):
|
|
70
135
|
data = self.public_key + json_string + self.public_key
|
|
71
136
|
hmac_hash = hmac.new(
|
|
@@ -3,24 +3,71 @@
|
|
|
3
3
|
# the most popular endpoints
|
|
4
4
|
# Full list of the Stripe API endpoints you can find here: https://stripe.com/docs/api.
|
|
5
5
|
ENDPOINTS = {
|
|
6
|
-
"subscription": "Subscription",
|
|
7
6
|
"account": "Account",
|
|
7
|
+
"applepaydomain": "ApplePayDomain",
|
|
8
|
+
"apple_pay_domain": "ApplePayDomain",
|
|
9
|
+
"applicationfee": "ApplicationFee",
|
|
10
|
+
"application_fee": "ApplicationFee",
|
|
11
|
+
"checkoutsession": "CheckoutSession",
|
|
12
|
+
"checkout_session": "CheckoutSession",
|
|
8
13
|
"coupon": "Coupon",
|
|
9
14
|
"customer": "Customer",
|
|
10
|
-
"
|
|
15
|
+
"dispute": "Dispute",
|
|
16
|
+
"paymentintent": "PaymentIntent",
|
|
17
|
+
"payment_intent": "PaymentIntent",
|
|
18
|
+
"paymentlink": "PaymentLink",
|
|
19
|
+
"payment_link": "PaymentLink",
|
|
20
|
+
"paymentmethod": "PaymentMethod",
|
|
21
|
+
"payment_method": "PaymentMethod",
|
|
22
|
+
"paymentmethoddomain": "PaymentMethodDomain",
|
|
23
|
+
"payment_method_domain": "PaymentMethodDomain",
|
|
24
|
+
"payout": "Payout",
|
|
25
|
+
"plan": "Plan",
|
|
11
26
|
"price": "Price",
|
|
27
|
+
"product": "Product",
|
|
28
|
+
"promotioncode": "PromotionCode",
|
|
29
|
+
"promotion_code": "PromotionCode",
|
|
30
|
+
"quote": "Quote",
|
|
31
|
+
"refund": "Refund",
|
|
32
|
+
"review": "Review",
|
|
33
|
+
"setupattempt": "SetupAttempt",
|
|
34
|
+
"setup_attempt": "SetupAttempt",
|
|
35
|
+
"setupintent": "SetupIntent",
|
|
36
|
+
"setup_intent": "SetupIntent",
|
|
12
37
|
"shippingrate": "ShippingRate",
|
|
13
|
-
"
|
|
38
|
+
"shipping_rate": "ShippingRate",
|
|
39
|
+
"subscription": "Subscription",
|
|
14
40
|
"subscriptionitem": "SubscriptionItem",
|
|
15
|
-
"
|
|
41
|
+
"subscription_item": "SubscriptionItem",
|
|
42
|
+
"subscriptionschedule": "SubscriptionSchedule",
|
|
43
|
+
"subscription_schedule": "SubscriptionSchedule",
|
|
44
|
+
"transfer": "Transfer",
|
|
45
|
+
"taxcode": "TaxCode",
|
|
46
|
+
"tax_code": "TaxCode",
|
|
47
|
+
"taxid": "TaxId",
|
|
48
|
+
"tax_id": "TaxId",
|
|
49
|
+
"taxrate": "TaxRate",
|
|
50
|
+
"tax_rate": "TaxRate",
|
|
51
|
+
"topup": "Topup",
|
|
52
|
+
"top_up": "Topup",
|
|
53
|
+
"webhookendpoint": "WebhookEndpoint",
|
|
54
|
+
"webhook_endpoint": "WebhookEndpoint",
|
|
16
55
|
}
|
|
17
56
|
# possible incremental endpoints
|
|
18
57
|
INCREMENTAL_ENDPOINTS = {
|
|
19
|
-
"
|
|
20
|
-
"
|
|
58
|
+
"applicationfee": "ApplicationFee",
|
|
59
|
+
"application_fee": "ApplicationFee",
|
|
21
60
|
"balancetransaction": "BalanceTransaction",
|
|
61
|
+
"balance_transaction": "BalanceTransaction",
|
|
22
62
|
"charge": "Charge",
|
|
23
|
-
"applicationfee": "ApplicationFee",
|
|
24
|
-
"setupattempt": "SetupAttempt",
|
|
25
63
|
"creditnote": "CreditNote",
|
|
64
|
+
"credit_note": "CreditNote",
|
|
65
|
+
"event": "Event",
|
|
66
|
+
"invoice": "Invoice",
|
|
67
|
+
"invoiceitem": "InvoiceItem",
|
|
68
|
+
"invoice_item": "InvoiceItem",
|
|
69
|
+
"invoicelineitem": "InvoiceLineItem",
|
|
70
|
+
"invoice_line_item": "InvoiceLineItem",
|
|
71
|
+
"setupattempt": "SetupAttempt",
|
|
72
|
+
"setup_attempt": "SetupAttempt",
|
|
26
73
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ingestr
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.51
|
|
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
|
|
@@ -2,12 +2,12 @@ ingestr/conftest.py,sha256=Q03FIJIZpLBbpj55cfCHIKEjc1FCvWJhMF2cidUJKQU,1748
|
|
|
2
2
|
ingestr/main.py,sha256=rHxHQAbd0ccW2e2kQSWlv7-5qcc2ZB6Eh3vyjm4Nzns,25550
|
|
3
3
|
ingestr/src/.gitignore,sha256=8cX1AZTSI0TcdZFGTmS_oyBjpfCzhOEt0DdAo2dFIY8,203
|
|
4
4
|
ingestr/src/blob.py,sha256=onMe5ZHxPXTdcB_s2oGNdMo-XQJ3ajwOsWE9eSTGFmc,1495
|
|
5
|
-
ingestr/src/buildinfo.py,sha256=
|
|
5
|
+
ingestr/src/buildinfo.py,sha256=ZgugQZPIlr-_7kRH5qIupQ5e48JTOHSlRWEsmNx4wXw,21
|
|
6
6
|
ingestr/src/destinations.py,sha256=41Bj1UgxR8a2KcZWqtGw74AKZKnSBrueQRnBdrf3c-A,16003
|
|
7
7
|
ingestr/src/errors.py,sha256=Ufs4_DfE77_E3vnA1fOQdi6cmuLVNm7_SbFLkL1XPGk,686
|
|
8
|
-
ingestr/src/factory.py,sha256=
|
|
8
|
+
ingestr/src/factory.py,sha256=JeK0M8C05-_KxxIhtevs-MJGLlngXUQupd-Pm4Fg904,5803
|
|
9
9
|
ingestr/src/filters.py,sha256=C-_TIVkF_cxZBgG-Run2Oyn0TAhJgA8IWXZ-OPY3uek,1136
|
|
10
|
-
ingestr/src/http_client.py,sha256=
|
|
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/partition.py,sha256=BrIP6wFJvyR7Nus_3ElnfxknUXeCipK_E_bB8kZowfc,969
|
|
13
13
|
ingestr/src/resource.py,sha256=ZqmZxFQVGlF8rFPhBiUB08HES0yoTj8sZ--jKfaaVps,1164
|
|
@@ -109,13 +109,13 @@ ingestr/src/slack/__init__.py,sha256=pyDukxcilqTAe_bBzfWJ8Vxi83S-XEdEFBH2pEgILrM
|
|
|
109
109
|
ingestr/src/slack/helpers.py,sha256=08TLK7vhFvH_uekdLVOLF3bTDe1zgH0QxHObXHzk1a8,6545
|
|
110
110
|
ingestr/src/slack/settings.py,sha256=NhKn4y1zokEa5EmIZ05wtj_-I0GOASXZ5V81M1zXCtY,457
|
|
111
111
|
ingestr/src/smartsheets/__init__.py,sha256=pdzSV7rA0XYD5Xa1u4zb6vziy5iFXIQNROkpJ9oYas0,1623
|
|
112
|
-
ingestr/src/solidgate/__init__.py,sha256=
|
|
113
|
-
ingestr/src/solidgate/helpers.py,sha256=
|
|
112
|
+
ingestr/src/solidgate/__init__.py,sha256=DZYQ4M3Cc7AIbdQcNQm_6yX2whnFhE-iM10-ACJ3W3A,3626
|
|
113
|
+
ingestr/src/solidgate/helpers.py,sha256=oePEc9nnvmN3IaKrfJCvyKL79xdGM0-gRTN3-8tY4Fc,4952
|
|
114
114
|
ingestr/src/sql_database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
115
115
|
ingestr/src/sql_database/callbacks.py,sha256=sEFFmXxAURY3yeBjnawigDtq9LBCvi8HFqG4kLd7tMU,2002
|
|
116
116
|
ingestr/src/stripe_analytics/__init__.py,sha256=FBkZu5op5Z-FceEi4zG7qcAgZfUYJRPMVPPrPMjvmXw,4502
|
|
117
117
|
ingestr/src/stripe_analytics/helpers.py,sha256=iqZOyiGIOhOAhVXXU16DP0hkkTKcTrDu69vAJoTxgEo,1976
|
|
118
|
-
ingestr/src/stripe_analytics/settings.py,sha256=
|
|
118
|
+
ingestr/src/stripe_analytics/settings.py,sha256=ZahhZg3Sq2KnvnDcfSaXO494Csy3tElBDEHnvA1AVmA,2461
|
|
119
119
|
ingestr/src/telemetry/event.py,sha256=W7bs4uVfPakQ5otmiqgqu1l5SqjYx1p87wudnWXckBc,949
|
|
120
120
|
ingestr/src/testdata/fakebqcredentials.json,sha256=scc6TUc963KAbKTLZCfcmqVzbtzDCW1_8JNRnyAXyy8,628
|
|
121
121
|
ingestr/src/tiktok_ads/__init__.py,sha256=aEqCl3dTH6_d43s1jgAeG1UasEls_SlorORulYMwIL8,4590
|
|
@@ -135,8 +135,8 @@ ingestr/testdata/merge_expected.csv,sha256=DReHqWGnQMsf2PBv_Q2pfjsgvikYFnf1zYcQZ
|
|
|
135
135
|
ingestr/testdata/merge_part1.csv,sha256=Pw8Z9IDKcNU0qQHx1z6BUf4rF_-SxKGFOvymCt4OY9I,185
|
|
136
136
|
ingestr/testdata/merge_part2.csv,sha256=T_GiWxA81SN63_tMOIuemcvboEFeAmbKc7xRXvL9esw,287
|
|
137
137
|
ingestr/tests/unit/test_smartsheets.py,sha256=eiC2CCO4iNJcuN36ONvqmEDryCA1bA1REpayHpu42lk,5058
|
|
138
|
-
ingestr-0.13.
|
|
139
|
-
ingestr-0.13.
|
|
140
|
-
ingestr-0.13.
|
|
141
|
-
ingestr-0.13.
|
|
142
|
-
ingestr-0.13.
|
|
138
|
+
ingestr-0.13.51.dist-info/METADATA,sha256=danPRyBhqlvyOwtw8kBmBh5FEY_xH6upsy5GrsFaMg4,13983
|
|
139
|
+
ingestr-0.13.51.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
140
|
+
ingestr-0.13.51.dist-info/entry_points.txt,sha256=oPJy0KBnPWYjDtP1k8qwAihcTLHSZokSQvRAw_wtfJM,46
|
|
141
|
+
ingestr-0.13.51.dist-info/licenses/LICENSE.md,sha256=cW8wIhn8HFE-KLStDF9jHQ1O_ARWP3kTpk_-eOccL24,1075
|
|
142
|
+
ingestr-0.13.51.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|