gr4vy 1.1.29__py3-none-any.whl → 1.10.9__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.
- gr4vy/_version.py +3 -3
- gr4vy/account_updater.py +6 -3
- gr4vy/actions.py +307 -0
- gr4vy/all.py +4 -2
- gr4vy/audit_logs.py +6 -4
- gr4vy/balances.py +4 -2
- gr4vy/basesdk.py +17 -1
- gr4vy/buyers_gift_cards.py +4 -2
- gr4vy/buyers_payment_methods.py +4 -2
- gr4vy/buyers_sdk.py +43 -25
- gr4vy/buyers_shipping_details.py +26 -16
- gr4vy/card_scheme_definitions_sdk.py +4 -2
- gr4vy/checkout_sessions.py +40 -14
- gr4vy/digital_wallets_sdk.py +32 -20
- gr4vy/domains.py +14 -10
- gr4vy/errors/__init__.py +15 -3
- gr4vy/errors/apierror.py +2 -0
- gr4vy/errors/error400.py +4 -6
- gr4vy/errors/error401.py +4 -6
- gr4vy/errors/error403.py +4 -6
- gr4vy/errors/error404.py +4 -6
- gr4vy/errors/error405.py +4 -6
- gr4vy/errors/error409.py +4 -6
- gr4vy/errors/error425.py +4 -6
- gr4vy/errors/error429.py +4 -6
- gr4vy/errors/error500.py +4 -6
- gr4vy/errors/error502.py +4 -6
- gr4vy/errors/error504.py +4 -6
- gr4vy/errors/gr4vyerror.py +11 -7
- gr4vy/errors/httpvalidationerror.py +4 -2
- gr4vy/errors/no_response_error.py +5 -1
- gr4vy/errors/responsevalidationerror.py +2 -0
- gr4vy/events.py +54 -7
- gr4vy/executions.py +38 -8
- gr4vy/gift_cards_sdk.py +29 -19
- gr4vy/httpclient.py +0 -1
- gr4vy/jobs.py +4 -2
- gr4vy/merchant_accounts_sdk.py +30 -10
- gr4vy/models/__init__.py +184 -30
- gr4vy/models/adyenautorescuesepascenariosenum.py +3 -1
- gr4vy/models/adyencardoptions.py +9 -6
- gr4vy/models/adyensepaoptions.py +1 -6
- gr4vy/models/adyensplitsoptions.py +57 -0
- gr4vy/models/airline.py +9 -8
- gr4vy/models/airlineleg.py +9 -7
- gr4vy/models/airlinepassenger.py +9 -7
- gr4vy/models/antifrauddecision.py +9 -1
- gr4vy/models/approvaltarget.py +7 -1
- gr4vy/models/auditlogaction.py +9 -1
- gr4vy/models/auditlogentry.py +3 -3
- gr4vy/models/auditlogentryuser.py +3 -3
- gr4vy/models/{billingdetails_input.py → billingdetails.py} +2 -2
- gr4vy/models/braintreedynamicdatafieldsoptions.py +33 -3
- gr4vy/models/browserinfo.py +9 -5
- gr4vy/models/buyer.py +3 -3
- gr4vy/models/buyercreate.py +3 -3
- gr4vy/models/buyerupdate.py +3 -3
- gr4vy/models/cancel_transactionop.py +43 -0
- gr4vy/models/cancelstatus.py +15 -0
- gr4vy/models/capturestatus.py +7 -1
- gr4vy/models/cardtype.py +8 -1
- gr4vy/models/cartitem.py +53 -8
- gr4vy/models/chaseoptions.py +46 -0
- gr4vy/models/checkoutsession.py +24 -3
- gr4vy/models/checkoutsessioncreate.py +39 -5
- gr4vy/models/checkoutsessionpaymentmethod.py +3 -5
- gr4vy/models/checkoutsessionpaymentmethoddetails.py +2 -6
- gr4vy/models/create_payment_methodop.py +6 -0
- gr4vy/models/create_report_execution_urlop.py +16 -1
- gr4vy/models/createsession.py +3 -3
- gr4vy/models/createsessionstatus.py +7 -1
- gr4vy/models/cvvresponsecode.py +7 -1
- gr4vy/models/cybersourceoptions.py +7 -0
- gr4vy/models/definitionfield.py +1 -6
- gr4vy/models/definitionfieldformat.py +8 -1
- gr4vy/models/digitalwallet.py +3 -5
- gr4vy/models/digitalwalletcreate.py +2 -6
- gr4vy/models/digitalwalletprovider.py +6 -1
- gr4vy/models/dlocalupioptions.py +50 -0
- gr4vy/models/dlocalupirecurringinfooptions.py +47 -0
- gr4vy/models/dlocalupiwalletoptions.py +89 -0
- gr4vy/models/errordetail.py +2 -4
- gr4vy/models/errorlocation.py +8 -1
- gr4vy/models/flow.py +16 -0
- gr4vy/models/flowaction.py +16 -0
- gr4vy/models/forterantifraudoptions.py +8 -8
- gr4vy/models/forterantifraudoptionscartitembasicitemdata.py +10 -8
- gr4vy/models/forterantifraudoptionscartitemdeliverydetails.py +9 -7
- gr4vy/models/giftcardredemption.py +4 -8
- gr4vy/models/giftcardredemptionstatus.py +7 -1
- gr4vy/models/giftcardservice.py +3 -5
- gr4vy/models/giftcardserviceprovider.py +5 -1
- gr4vy/models/giftcardsummary.py +3 -5
- gr4vy/models/{guestbuyer_input.py → guestbuyer.py} +5 -5
- gr4vy/models/instrumenttype.py +1 -0
- gr4vy/models/integrationclient.py +16 -0
- gr4vy/models/internal/__init__.py +14 -1
- gr4vy/models/list_all_report_executionsop.py +2 -14
- gr4vy/models/list_audit_logsop.py +2 -10
- gr4vy/models/list_buyer_payment_methodsop.py +9 -4
- gr4vy/models/list_payment_methodsop.py +2 -14
- gr4vy/models/list_payment_servicesop.py +2 -8
- gr4vy/models/list_reportsop.py +2 -10
- gr4vy/models/list_transaction_actionsop.py +43 -0
- gr4vy/models/list_transaction_eventsop.py +12 -1
- gr4vy/models/list_transactionsop.py +14 -22
- gr4vy/models/merchantaccount.py +9 -5
- gr4vy/models/merchantaccountcreate.py +8 -6
- gr4vy/models/merchantaccountupdate.py +8 -6
- gr4vy/models/merchantprofilescheme.py +7 -7
- gr4vy/models/merchantprofileschemesummary.py +7 -7
- gr4vy/models/method.py +4 -0
- gr4vy/models/mockcardoptions.py +7 -2
- gr4vy/models/mode.py +1 -0
- gr4vy/models/monatospeioptions.py +15 -0
- gr4vy/models/networktoken.py +3 -3
- gr4vy/models/networktokenpaymentmethodcreate.py +11 -9
- gr4vy/models/networktokenstatus.py +7 -1
- gr4vy/models/nuveiidealoptions.py +49 -0
- gr4vy/models/nuveipseoptions.py +70 -0
- gr4vy/models/paymentlink.py +25 -7
- gr4vy/models/paymentlinkcreate.py +23 -28
- gr4vy/models/paymentlinkstatus.py +7 -1
- gr4vy/models/paymentmethod.py +7 -13
- gr4vy/models/paymentmethodcard.py +3 -5
- gr4vy/models/paymentmethoddetailscard.py +2 -6
- gr4vy/models/paymentmethodstatus.py +7 -1
- gr4vy/models/paymentmethodsummary.py +6 -12
- gr4vy/models/paymentoption.py +3 -3
- gr4vy/models/paymentservice.py +4 -6
- gr4vy/models/paymentserviceconfiguration.py +2 -6
- gr4vy/models/paymentservicedefinition.py +11 -5
- gr4vy/models/paymentservicestatus.py +8 -1
- gr4vy/models/paymentservicetoken.py +3 -3
- gr4vy/models/payoutcategory.py +1 -1
- gr4vy/models/payoutcreate.py +5 -9
- gr4vy/models/payoutstatus.py +7 -1
- gr4vy/models/payoutsummary.py +4 -6
- gr4vy/models/paypaloptions.py +8 -2
- gr4vy/models/paypalshippingoptions.py +51 -0
- gr4vy/models/paypalshippingoptionsitem.py +89 -0
- gr4vy/models/paypalshippingoptionsitemamount.py +20 -0
- gr4vy/models/plaidpaymentmethodcreate.py +106 -0
- gr4vy/models/redirectpaymentmethodcreate.py +4 -6
- gr4vy/models/refund.py +4 -4
- gr4vy/models/refundstatus.py +8 -1
- gr4vy/models/refundtargettype.py +5 -1
- gr4vy/models/report.py +4 -6
- gr4vy/models/reportcreate.py +2 -3
- gr4vy/models/reportcreatortype.py +7 -1
- gr4vy/models/reportexecution.py +3 -3
- gr4vy/models/reportexecutionstatus.py +7 -1
- gr4vy/models/reportexecutionsummary.py +3 -3
- gr4vy/models/reportexecutionurlgenerate.py +16 -0
- gr4vy/models/reportschedule.py +9 -1
- gr4vy/models/reportspec.py +2 -4
- gr4vy/models/reportsummary.py +3 -5
- gr4vy/models/settlement.py +32 -32
- gr4vy/models/statementdescriptor.py +7 -0
- gr4vy/models/stripeconnectoptions.py +7 -0
- gr4vy/models/taxid.py +2 -4
- gr4vy/models/taxidkind.py +7 -0
- gr4vy/models/threedsecuredatav1.py +2 -6
- gr4vy/models/threedsecuredatav2.py +2 -6
- gr4vy/models/threedsecuremethod.py +7 -1
- gr4vy/models/threedsecurestatus.py +7 -1
- gr4vy/models/transaction.py +86 -25
- gr4vy/models/transactionaction.py +48 -0
- gr4vy/models/transactionactions.py +17 -0
- gr4vy/models/transactionbuyer.py +3 -3
- gr4vy/models/transactioncancel.py +81 -0
- gr4vy/models/transactioncapture.py +3 -3
- gr4vy/models/transactionconnectionoptions.py +50 -0
- gr4vy/models/transactioncreate.py +76 -12
- gr4vy/models/transactionevent.py +10 -3
- gr4vy/models/transactionintent.py +7 -1
- gr4vy/models/transactionintentoutcome.py +6 -1
- gr4vy/models/transactionpaymentmethod.py +6 -12
- gr4vy/models/transactionpaymentservice.py +3 -3
- gr4vy/models/transactionpaymentsource.py +7 -1
- gr4vy/models/transactionrefundcreate.py +2 -6
- gr4vy/models/transactionsummary.py +11 -10
- gr4vy/models/transactionthreedsecuresummary.py +3 -9
- gr4vy/models/transactionvoid.py +3 -3
- gr4vy/models/userstatus.py +8 -1
- gr4vy/models/voidstatus.py +7 -1
- gr4vy/network_tokens_cryptogram.py +4 -2
- gr4vy/payment_links_sdk.py +36 -16
- gr4vy/payment_methods_network_tokens.py +27 -13
- gr4vy/payment_methods_payment_service_tokens.py +12 -6
- gr4vy/payment_methods_sdk.py +26 -14
- gr4vy/payment_options_sdk.py +4 -2
- gr4vy/payment_service_definitions_sdk.py +14 -8
- gr4vy/payment_services_sdk.py +36 -22
- gr4vy/payouts.py +18 -12
- gr4vy/refunds_sdk.py +4 -2
- gr4vy/report_executions_sdk.py +6 -4
- gr4vy/reports_sdk.py +23 -13
- gr4vy/sdk.py +17 -4
- gr4vy/sessions.py +12 -6
- gr4vy/transactions.py +446 -33
- gr4vy/transactions_refunds.py +17 -9
- gr4vy/transactions_settlements.py +8 -4
- gr4vy/types/basemodel.py +41 -3
- gr4vy/utils/__init__.py +15 -6
- gr4vy/utils/annotations.py +32 -8
- gr4vy/utils/enums.py +60 -0
- gr4vy/utils/eventstreaming.py +10 -0
- gr4vy/utils/forms.py +21 -10
- gr4vy/utils/queryparams.py +14 -2
- gr4vy/utils/requestbodies.py +1 -1
- gr4vy/utils/retries.py +69 -5
- gr4vy/utils/serializers.py +0 -20
- gr4vy/utils/unmarshal_json_response.py +15 -1
- {gr4vy-1.1.29.dist-info → gr4vy-1.10.9.dist-info}/METADATA +43 -41
- {gr4vy-1.1.29.dist-info → gr4vy-1.10.9.dist-info}/RECORD +217 -196
- {gr4vy-1.1.29.dist-info → gr4vy-1.10.9.dist-info}/WHEEL +1 -1
- gr4vy/models/billingdetails_output.py +0 -87
- gr4vy/models/guestbuyer_output.py +0 -80
gr4vy/transactions_refunds.py
CHANGED
|
@@ -14,13 +14,15 @@ from typing import Any, Mapping, Optional
|
|
|
14
14
|
class TransactionsRefunds(BaseSDK):
|
|
15
15
|
all: All
|
|
16
16
|
|
|
17
|
-
def __init__(
|
|
18
|
-
|
|
17
|
+
def __init__(
|
|
18
|
+
self, sdk_config: SDKConfiguration, parent_ref: Optional[object] = None
|
|
19
|
+
) -> None:
|
|
20
|
+
BaseSDK.__init__(self, sdk_config, parent_ref=parent_ref)
|
|
19
21
|
self.sdk_configuration = sdk_config
|
|
20
22
|
self._init_sdks()
|
|
21
23
|
|
|
22
24
|
def _init_sdks(self):
|
|
23
|
-
self.all = All(self.sdk_configuration)
|
|
25
|
+
self.all = All(self.sdk_configuration, parent_ref=self.parent_ref)
|
|
24
26
|
|
|
25
27
|
def list(
|
|
26
28
|
self,
|
|
@@ -74,6 +76,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
74
76
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
75
77
|
),
|
|
76
78
|
security=self.sdk_configuration.security,
|
|
79
|
+
allow_empty_value=None,
|
|
77
80
|
timeout_ms=timeout_ms,
|
|
78
81
|
)
|
|
79
82
|
|
|
@@ -94,7 +97,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
94
97
|
config=self.sdk_configuration,
|
|
95
98
|
base_url=base_url or "",
|
|
96
99
|
operation_id="list_transaction_refunds",
|
|
97
|
-
oauth2_scopes=
|
|
100
|
+
oauth2_scopes=None,
|
|
98
101
|
security_source=get_security_from_env(
|
|
99
102
|
self.sdk_configuration.security, models.Security
|
|
100
103
|
),
|
|
@@ -221,6 +224,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
221
224
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
222
225
|
),
|
|
223
226
|
security=self.sdk_configuration.security,
|
|
227
|
+
allow_empty_value=None,
|
|
224
228
|
timeout_ms=timeout_ms,
|
|
225
229
|
)
|
|
226
230
|
|
|
@@ -241,7 +245,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
241
245
|
config=self.sdk_configuration,
|
|
242
246
|
base_url=base_url or "",
|
|
243
247
|
operation_id="list_transaction_refunds",
|
|
244
|
-
oauth2_scopes=
|
|
248
|
+
oauth2_scopes=None,
|
|
245
249
|
security_source=get_security_from_env(
|
|
246
250
|
self.sdk_configuration.security, models.Security
|
|
247
251
|
),
|
|
@@ -392,6 +396,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
392
396
|
"json",
|
|
393
397
|
models.TransactionRefundCreate,
|
|
394
398
|
),
|
|
399
|
+
allow_empty_value=None,
|
|
395
400
|
timeout_ms=timeout_ms,
|
|
396
401
|
)
|
|
397
402
|
|
|
@@ -408,7 +413,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
408
413
|
config=self.sdk_configuration,
|
|
409
414
|
base_url=base_url or "",
|
|
410
415
|
operation_id="create_transaction_refund",
|
|
411
|
-
oauth2_scopes=
|
|
416
|
+
oauth2_scopes=None,
|
|
412
417
|
security_source=get_security_from_env(
|
|
413
418
|
self.sdk_configuration.security, models.Security
|
|
414
419
|
),
|
|
@@ -559,6 +564,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
559
564
|
"json",
|
|
560
565
|
models.TransactionRefundCreate,
|
|
561
566
|
),
|
|
567
|
+
allow_empty_value=None,
|
|
562
568
|
timeout_ms=timeout_ms,
|
|
563
569
|
)
|
|
564
570
|
|
|
@@ -575,7 +581,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
575
581
|
config=self.sdk_configuration,
|
|
576
582
|
base_url=base_url or "",
|
|
577
583
|
operation_id="create_transaction_refund",
|
|
578
|
-
oauth2_scopes=
|
|
584
|
+
oauth2_scopes=None,
|
|
579
585
|
security_source=get_security_from_env(
|
|
580
586
|
self.sdk_configuration.security, models.Security
|
|
581
587
|
),
|
|
@@ -705,6 +711,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
705
711
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
706
712
|
),
|
|
707
713
|
security=self.sdk_configuration.security,
|
|
714
|
+
allow_empty_value=None,
|
|
708
715
|
timeout_ms=timeout_ms,
|
|
709
716
|
)
|
|
710
717
|
|
|
@@ -725,7 +732,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
725
732
|
config=self.sdk_configuration,
|
|
726
733
|
base_url=base_url or "",
|
|
727
734
|
operation_id="get_transaction_refund",
|
|
728
|
-
oauth2_scopes=
|
|
735
|
+
oauth2_scopes=None,
|
|
729
736
|
security_source=get_security_from_env(
|
|
730
737
|
self.sdk_configuration.security, models.Security
|
|
731
738
|
),
|
|
@@ -855,6 +862,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
855
862
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
856
863
|
),
|
|
857
864
|
security=self.sdk_configuration.security,
|
|
865
|
+
allow_empty_value=None,
|
|
858
866
|
timeout_ms=timeout_ms,
|
|
859
867
|
)
|
|
860
868
|
|
|
@@ -875,7 +883,7 @@ class TransactionsRefunds(BaseSDK):
|
|
|
875
883
|
config=self.sdk_configuration,
|
|
876
884
|
base_url=base_url or "",
|
|
877
885
|
operation_id="get_transaction_refund",
|
|
878
|
-
oauth2_scopes=
|
|
886
|
+
oauth2_scopes=None,
|
|
879
887
|
security_source=get_security_from_env(
|
|
880
888
|
self.sdk_configuration.security, models.Security
|
|
881
889
|
),
|
|
@@ -65,6 +65,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
65
65
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
66
66
|
),
|
|
67
67
|
security=self.sdk_configuration.security,
|
|
68
|
+
allow_empty_value=None,
|
|
68
69
|
timeout_ms=timeout_ms,
|
|
69
70
|
)
|
|
70
71
|
|
|
@@ -85,7 +86,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
85
86
|
config=self.sdk_configuration,
|
|
86
87
|
base_url=base_url or "",
|
|
87
88
|
operation_id="get_transaction_settlement",
|
|
88
|
-
oauth2_scopes=
|
|
89
|
+
oauth2_scopes=None,
|
|
89
90
|
security_source=get_security_from_env(
|
|
90
91
|
self.sdk_configuration.security, models.Security
|
|
91
92
|
),
|
|
@@ -215,6 +216,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
215
216
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
216
217
|
),
|
|
217
218
|
security=self.sdk_configuration.security,
|
|
219
|
+
allow_empty_value=None,
|
|
218
220
|
timeout_ms=timeout_ms,
|
|
219
221
|
)
|
|
220
222
|
|
|
@@ -235,7 +237,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
235
237
|
config=self.sdk_configuration,
|
|
236
238
|
base_url=base_url or "",
|
|
237
239
|
operation_id="get_transaction_settlement",
|
|
238
|
-
oauth2_scopes=
|
|
240
|
+
oauth2_scopes=None,
|
|
239
241
|
security_source=get_security_from_env(
|
|
240
242
|
self.sdk_configuration.security, models.Security
|
|
241
243
|
),
|
|
@@ -362,6 +364,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
362
364
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
363
365
|
),
|
|
364
366
|
security=self.sdk_configuration.security,
|
|
367
|
+
allow_empty_value=None,
|
|
365
368
|
timeout_ms=timeout_ms,
|
|
366
369
|
)
|
|
367
370
|
|
|
@@ -382,7 +385,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
382
385
|
config=self.sdk_configuration,
|
|
383
386
|
base_url=base_url or "",
|
|
384
387
|
operation_id="list_transaction_settlements",
|
|
385
|
-
oauth2_scopes=
|
|
388
|
+
oauth2_scopes=None,
|
|
386
389
|
security_source=get_security_from_env(
|
|
387
390
|
self.sdk_configuration.security, models.Security
|
|
388
391
|
),
|
|
@@ -509,6 +512,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
509
512
|
merchant_account_id=self.sdk_configuration.globals.merchant_account_id,
|
|
510
513
|
),
|
|
511
514
|
security=self.sdk_configuration.security,
|
|
515
|
+
allow_empty_value=None,
|
|
512
516
|
timeout_ms=timeout_ms,
|
|
513
517
|
)
|
|
514
518
|
|
|
@@ -529,7 +533,7 @@ class TransactionsSettlements(BaseSDK):
|
|
|
529
533
|
config=self.sdk_configuration,
|
|
530
534
|
base_url=base_url or "",
|
|
531
535
|
operation_id="list_transaction_settlements",
|
|
532
|
-
oauth2_scopes=
|
|
536
|
+
oauth2_scopes=None,
|
|
533
537
|
security_source=get_security_from_env(
|
|
534
538
|
self.sdk_configuration.security, models.Security
|
|
535
539
|
),
|
gr4vy/types/basemodel.py
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from pydantic import ConfigDict, model_serializer
|
|
4
4
|
from pydantic import BaseModel as PydanticBaseModel
|
|
5
|
-
from
|
|
5
|
+
from pydantic_core import core_schema
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union
|
|
6
7
|
from typing_extensions import TypeAliasType, TypeAlias
|
|
7
8
|
|
|
8
9
|
|
|
@@ -35,5 +36,42 @@ else:
|
|
|
35
36
|
"OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,)
|
|
36
37
|
)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
UnrecognizedStr:
|
|
39
|
+
|
|
40
|
+
class UnrecognizedStr(str):
|
|
41
|
+
@classmethod
|
|
42
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
|
|
43
|
+
# Make UnrecognizedStr only work in lax mode, not strict mode
|
|
44
|
+
# This makes it a "fallback" option when more specific types (like Literals) don't match
|
|
45
|
+
def validate_lax(v: Any) -> 'UnrecognizedStr':
|
|
46
|
+
if isinstance(v, cls):
|
|
47
|
+
return v
|
|
48
|
+
return cls(str(v))
|
|
49
|
+
|
|
50
|
+
# Use lax_or_strict_schema where strict always fails
|
|
51
|
+
# This forces Pydantic to prefer other union members in strict mode
|
|
52
|
+
# and only fall back to UnrecognizedStr in lax mode
|
|
53
|
+
return core_schema.lax_or_strict_schema(
|
|
54
|
+
lax_schema=core_schema.chain_schema([
|
|
55
|
+
core_schema.str_schema(),
|
|
56
|
+
core_schema.no_info_plain_validator_function(validate_lax)
|
|
57
|
+
]),
|
|
58
|
+
strict_schema=core_schema.none_schema(), # Always fails in strict mode
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class UnrecognizedInt(int):
|
|
63
|
+
@classmethod
|
|
64
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
|
|
65
|
+
# Make UnrecognizedInt only work in lax mode, not strict mode
|
|
66
|
+
# This makes it a "fallback" option when more specific types (like Literals) don't match
|
|
67
|
+
def validate_lax(v: Any) -> 'UnrecognizedInt':
|
|
68
|
+
if isinstance(v, cls):
|
|
69
|
+
return v
|
|
70
|
+
return cls(int(v))
|
|
71
|
+
return core_schema.lax_or_strict_schema(
|
|
72
|
+
lax_schema=core_schema.chain_schema([
|
|
73
|
+
core_schema.int_schema(),
|
|
74
|
+
core_schema.no_info_plain_validator_function(validate_lax)
|
|
75
|
+
]),
|
|
76
|
+
strict_schema=core_schema.none_schema(), # Always fails in strict mode
|
|
77
|
+
)
|
gr4vy/utils/__init__.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
from importlib import import_module
|
|
5
5
|
import builtins
|
|
6
|
+
import sys
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from .annotations import get_discriminator
|
|
@@ -41,7 +42,6 @@ if TYPE_CHECKING:
|
|
|
41
42
|
validate_decimal,
|
|
42
43
|
validate_float,
|
|
43
44
|
validate_int,
|
|
44
|
-
validate_open_enum,
|
|
45
45
|
)
|
|
46
46
|
from .url import generate_url, template_url, remove_suffix
|
|
47
47
|
from .values import (
|
|
@@ -103,7 +103,6 @@ __all__ = [
|
|
|
103
103
|
"validate_const",
|
|
104
104
|
"validate_float",
|
|
105
105
|
"validate_int",
|
|
106
|
-
"validate_open_enum",
|
|
107
106
|
"cast_partial",
|
|
108
107
|
]
|
|
109
108
|
|
|
@@ -157,11 +156,22 @@ _dynamic_imports: dict[str, str] = {
|
|
|
157
156
|
"validate_const": ".serializers",
|
|
158
157
|
"validate_float": ".serializers",
|
|
159
158
|
"validate_int": ".serializers",
|
|
160
|
-
"validate_open_enum": ".serializers",
|
|
161
159
|
"cast_partial": ".values",
|
|
162
160
|
}
|
|
163
161
|
|
|
164
162
|
|
|
163
|
+
def dynamic_import(modname, retries=3):
|
|
164
|
+
for attempt in range(retries):
|
|
165
|
+
try:
|
|
166
|
+
return import_module(modname, __package__)
|
|
167
|
+
except KeyError:
|
|
168
|
+
# Clear any half-initialized module and retry
|
|
169
|
+
sys.modules.pop(modname, None)
|
|
170
|
+
if attempt == retries - 1:
|
|
171
|
+
break
|
|
172
|
+
raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")
|
|
173
|
+
|
|
174
|
+
|
|
165
175
|
def __getattr__(attr_name: str) -> object:
|
|
166
176
|
module_name = _dynamic_imports.get(attr_name)
|
|
167
177
|
if module_name is None:
|
|
@@ -170,9 +180,8 @@ def __getattr__(attr_name: str) -> object:
|
|
|
170
180
|
)
|
|
171
181
|
|
|
172
182
|
try:
|
|
173
|
-
module =
|
|
174
|
-
|
|
175
|
-
return result
|
|
183
|
+
module = dynamic_import(module_name)
|
|
184
|
+
return getattr(module, attr_name)
|
|
176
185
|
except ImportError as e:
|
|
177
186
|
raise ImportError(
|
|
178
187
|
f"Failed to import {attr_name} from {module_name}: {e}"
|
gr4vy/utils/annotations.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from typing import Any, Optional
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
def get_discriminator(model: Any, fieldname: str, key: str) -> str:
|
|
7
8
|
"""
|
|
8
9
|
Recursively search for the discriminator attribute in a model.
|
|
@@ -25,31 +26,54 @@ def get_discriminator(model: Any, fieldname: str, key: str) -> str:
|
|
|
25
26
|
|
|
26
27
|
if isinstance(field, dict):
|
|
27
28
|
if key in field:
|
|
28
|
-
return f
|
|
29
|
+
return f"{field[key]}"
|
|
29
30
|
|
|
30
31
|
if hasattr(field, fieldname):
|
|
31
32
|
attr = getattr(field, fieldname)
|
|
32
33
|
if isinstance(attr, Enum):
|
|
33
|
-
return f
|
|
34
|
-
return f
|
|
34
|
+
return f"{attr.value}"
|
|
35
|
+
return f"{attr}"
|
|
35
36
|
|
|
36
37
|
if hasattr(field, upper_fieldname):
|
|
37
38
|
attr = getattr(field, upper_fieldname)
|
|
38
39
|
if isinstance(attr, Enum):
|
|
39
|
-
return f
|
|
40
|
-
return f
|
|
40
|
+
return f"{attr.value}"
|
|
41
|
+
return f"{attr}"
|
|
41
42
|
|
|
42
43
|
return None
|
|
43
44
|
|
|
45
|
+
def search_nested_discriminator(obj: Any) -> Optional[str]:
|
|
46
|
+
"""Recursively search for discriminator in nested structures."""
|
|
47
|
+
# First try direct field lookup
|
|
48
|
+
discriminator = get_field_discriminator(obj)
|
|
49
|
+
if discriminator is not None:
|
|
50
|
+
return discriminator
|
|
51
|
+
|
|
52
|
+
# If it's a dict, search in nested values
|
|
53
|
+
if isinstance(obj, dict):
|
|
54
|
+
for value in obj.values():
|
|
55
|
+
if isinstance(value, list):
|
|
56
|
+
# Search in list items
|
|
57
|
+
for item in value:
|
|
58
|
+
nested_discriminator = search_nested_discriminator(item)
|
|
59
|
+
if nested_discriminator is not None:
|
|
60
|
+
return nested_discriminator
|
|
61
|
+
elif isinstance(value, dict):
|
|
62
|
+
# Search in nested dict
|
|
63
|
+
nested_discriminator = search_nested_discriminator(value)
|
|
64
|
+
if nested_discriminator is not None:
|
|
65
|
+
return nested_discriminator
|
|
66
|
+
|
|
67
|
+
return None
|
|
44
68
|
|
|
45
69
|
if isinstance(model, list):
|
|
46
70
|
for field in model:
|
|
47
|
-
discriminator =
|
|
71
|
+
discriminator = search_nested_discriminator(field)
|
|
48
72
|
if discriminator is not None:
|
|
49
73
|
return discriminator
|
|
50
74
|
|
|
51
|
-
discriminator =
|
|
75
|
+
discriminator = search_nested_discriminator(model)
|
|
52
76
|
if discriminator is not None:
|
|
53
77
|
return discriminator
|
|
54
78
|
|
|
55
|
-
raise ValueError(f
|
|
79
|
+
raise ValueError(f"Could not find discriminator field {fieldname} in {model}")
|
gr4vy/utils/enums.py
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import enum
|
|
4
4
|
import sys
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic_core import core_schema
|
|
8
|
+
|
|
5
9
|
|
|
6
10
|
class OpenEnumMeta(enum.EnumMeta):
|
|
7
11
|
# The __call__ method `boundary` kwarg was added in 3.11 and must be present
|
|
@@ -72,3 +76,59 @@ class OpenEnumMeta(enum.EnumMeta):
|
|
|
72
76
|
)
|
|
73
77
|
except ValueError:
|
|
74
78
|
return value
|
|
79
|
+
|
|
80
|
+
def __new__(mcs, name, bases, namespace, **kwargs):
|
|
81
|
+
cls = super().__new__(mcs, name, bases, namespace, **kwargs)
|
|
82
|
+
|
|
83
|
+
# Add __get_pydantic_core_schema__ to make open enums work correctly
|
|
84
|
+
# in union discrimination. In strict mode (used by Pydantic for unions),
|
|
85
|
+
# only known enum values match. In lax mode, unknown values are accepted.
|
|
86
|
+
def __get_pydantic_core_schema__(
|
|
87
|
+
cls_inner: Any, _source_type: Any, _handler: Any
|
|
88
|
+
) -> core_schema.CoreSchema:
|
|
89
|
+
# Create a validator that only accepts known enum values (for strict mode)
|
|
90
|
+
def validate_strict(v: Any) -> Any:
|
|
91
|
+
if isinstance(v, cls_inner):
|
|
92
|
+
return v
|
|
93
|
+
# Use the parent EnumMeta's __call__ which raises ValueError for unknown values
|
|
94
|
+
return enum.EnumMeta.__call__(cls_inner, v)
|
|
95
|
+
|
|
96
|
+
# Create a lax validator that accepts unknown values
|
|
97
|
+
def validate_lax(v: Any) -> Any:
|
|
98
|
+
if isinstance(v, cls_inner):
|
|
99
|
+
return v
|
|
100
|
+
try:
|
|
101
|
+
return enum.EnumMeta.__call__(cls_inner, v)
|
|
102
|
+
except ValueError:
|
|
103
|
+
# Return the raw value for unknown enum values
|
|
104
|
+
return v
|
|
105
|
+
|
|
106
|
+
# Determine the base type schema (str or int)
|
|
107
|
+
is_int_enum = False
|
|
108
|
+
for base in cls_inner.__mro__:
|
|
109
|
+
if base is int:
|
|
110
|
+
is_int_enum = True
|
|
111
|
+
break
|
|
112
|
+
if base is str:
|
|
113
|
+
break
|
|
114
|
+
|
|
115
|
+
base_schema = (
|
|
116
|
+
core_schema.int_schema()
|
|
117
|
+
if is_int_enum
|
|
118
|
+
else core_schema.str_schema()
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Use lax_or_strict_schema:
|
|
122
|
+
# - strict mode: only known enum values match (raises ValueError for unknown)
|
|
123
|
+
# - lax mode: accept any value, return enum member or raw value
|
|
124
|
+
return core_schema.lax_or_strict_schema(
|
|
125
|
+
lax_schema=core_schema.chain_schema(
|
|
126
|
+
[base_schema, core_schema.no_info_plain_validator_function(validate_lax)]
|
|
127
|
+
),
|
|
128
|
+
strict_schema=core_schema.chain_schema(
|
|
129
|
+
[base_schema, core_schema.no_info_plain_validator_function(validate_strict)]
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
setattr(cls, "__get_pydantic_core_schema__", classmethod(__get_pydantic_core_schema__))
|
|
134
|
+
return cls
|
gr4vy/utils/eventstreaming.py
CHANGED
|
@@ -17,6 +17,9 @@ T = TypeVar("T")
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class EventStream(Generic[T]):
|
|
20
|
+
# Holds a reference to the SDK client to avoid it being garbage collected
|
|
21
|
+
# and cause termination of the underlying httpx client.
|
|
22
|
+
client_ref: Optional[object]
|
|
20
23
|
response: httpx.Response
|
|
21
24
|
generator: Generator[T, None, None]
|
|
22
25
|
|
|
@@ -25,9 +28,11 @@ class EventStream(Generic[T]):
|
|
|
25
28
|
response: httpx.Response,
|
|
26
29
|
decoder: Callable[[str], T],
|
|
27
30
|
sentinel: Optional[str] = None,
|
|
31
|
+
client_ref: Optional[object] = None,
|
|
28
32
|
):
|
|
29
33
|
self.response = response
|
|
30
34
|
self.generator = stream_events(response, decoder, sentinel)
|
|
35
|
+
self.client_ref = client_ref
|
|
31
36
|
|
|
32
37
|
def __iter__(self):
|
|
33
38
|
return self
|
|
@@ -43,6 +48,9 @@ class EventStream(Generic[T]):
|
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
class EventStreamAsync(Generic[T]):
|
|
51
|
+
# Holds a reference to the SDK client to avoid it being garbage collected
|
|
52
|
+
# and cause termination of the underlying httpx client.
|
|
53
|
+
client_ref: Optional[object]
|
|
46
54
|
response: httpx.Response
|
|
47
55
|
generator: AsyncGenerator[T, None]
|
|
48
56
|
|
|
@@ -51,9 +59,11 @@ class EventStreamAsync(Generic[T]):
|
|
|
51
59
|
response: httpx.Response,
|
|
52
60
|
decoder: Callable[[str], T],
|
|
53
61
|
sentinel: Optional[str] = None,
|
|
62
|
+
client_ref: Optional[object] = None,
|
|
54
63
|
):
|
|
55
64
|
self.response = response
|
|
56
65
|
self.generator = stream_events_async(response, decoder, sentinel)
|
|
66
|
+
self.client_ref = client_ref
|
|
57
67
|
|
|
58
68
|
def __aiter__(self):
|
|
59
69
|
return self
|
gr4vy/utils/forms.py
CHANGED
|
@@ -142,16 +142,21 @@ def serialize_multipart_form(
|
|
|
142
142
|
if field_metadata.file:
|
|
143
143
|
if isinstance(val, List):
|
|
144
144
|
# Handle array of files
|
|
145
|
+
array_field_name = f_name + "[]"
|
|
145
146
|
for file_obj in val:
|
|
146
147
|
if not _is_set(file_obj):
|
|
147
148
|
continue
|
|
148
|
-
|
|
149
|
-
file_name, content, content_type = _extract_file_properties(
|
|
149
|
+
|
|
150
|
+
file_name, content, content_type = _extract_file_properties(
|
|
151
|
+
file_obj
|
|
152
|
+
)
|
|
150
153
|
|
|
151
154
|
if content_type is not None:
|
|
152
|
-
files.append(
|
|
155
|
+
files.append(
|
|
156
|
+
(array_field_name, (file_name, content, content_type))
|
|
157
|
+
)
|
|
153
158
|
else:
|
|
154
|
-
files.append((
|
|
159
|
+
files.append((array_field_name, (file_name, content)))
|
|
155
160
|
else:
|
|
156
161
|
# Handle single file
|
|
157
162
|
file_name, content, content_type = _extract_file_properties(val)
|
|
@@ -161,11 +166,16 @@ def serialize_multipart_form(
|
|
|
161
166
|
else:
|
|
162
167
|
files.append((f_name, (file_name, content)))
|
|
163
168
|
elif field_metadata.json:
|
|
164
|
-
files.append(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
files.append(
|
|
170
|
+
(
|
|
171
|
+
f_name,
|
|
172
|
+
(
|
|
173
|
+
None,
|
|
174
|
+
marshal_json(val, request_field_types[name]),
|
|
175
|
+
"application/json",
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
)
|
|
169
179
|
else:
|
|
170
180
|
if isinstance(val, List):
|
|
171
181
|
values = []
|
|
@@ -175,7 +185,8 @@ def serialize_multipart_form(
|
|
|
175
185
|
continue
|
|
176
186
|
values.append(_val_to_string(value))
|
|
177
187
|
|
|
178
|
-
|
|
188
|
+
array_field_name = f_name + "[]"
|
|
189
|
+
form[array_field_name] = values
|
|
179
190
|
else:
|
|
180
191
|
form[f_name] = _val_to_string(val)
|
|
181
192
|
return media_type, form, files
|
gr4vy/utils/queryparams.py
CHANGED
|
@@ -27,12 +27,13 @@ from .forms import _populate_form
|
|
|
27
27
|
def get_query_params(
|
|
28
28
|
query_params: Any,
|
|
29
29
|
gbls: Optional[Any] = None,
|
|
30
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
30
31
|
) -> Dict[str, List[str]]:
|
|
31
32
|
params: Dict[str, List[str]] = {}
|
|
32
33
|
|
|
33
|
-
globals_already_populated = _populate_query_params(query_params, gbls, params, [])
|
|
34
|
+
globals_already_populated = _populate_query_params(query_params, gbls, params, [], allow_empty_value)
|
|
34
35
|
if _is_set(gbls):
|
|
35
|
-
_populate_query_params(gbls, None, params, globals_already_populated)
|
|
36
|
+
_populate_query_params(gbls, None, params, globals_already_populated, allow_empty_value)
|
|
36
37
|
|
|
37
38
|
return params
|
|
38
39
|
|
|
@@ -42,6 +43,7 @@ def _populate_query_params(
|
|
|
42
43
|
gbls: Any,
|
|
43
44
|
query_param_values: Dict[str, List[str]],
|
|
44
45
|
skip_fields: List[str],
|
|
46
|
+
allow_empty_value: Optional[List[str]] = None,
|
|
45
47
|
) -> List[str]:
|
|
46
48
|
globals_already_populated: List[str] = []
|
|
47
49
|
|
|
@@ -69,6 +71,16 @@ def _populate_query_params(
|
|
|
69
71
|
globals_already_populated.append(name)
|
|
70
72
|
|
|
71
73
|
f_name = field.alias if field.alias is not None else name
|
|
74
|
+
|
|
75
|
+
allow_empty_set = set(allow_empty_value or [])
|
|
76
|
+
should_include_empty = f_name in allow_empty_set and (
|
|
77
|
+
value is None or value == [] or value == ""
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if should_include_empty:
|
|
81
|
+
query_param_values[f_name] = [""]
|
|
82
|
+
continue
|
|
83
|
+
|
|
72
84
|
serialization = metadata.serialization
|
|
73
85
|
if serialization is not None:
|
|
74
86
|
serialized_parms = _get_serialized_params(
|
gr4vy/utils/requestbodies.py
CHANGED
|
@@ -44,7 +44,7 @@ def serialize_request_body(
|
|
|
44
44
|
|
|
45
45
|
serialized_request_body = SerializedRequestBody(media_type)
|
|
46
46
|
|
|
47
|
-
if re.match(r"(application|text)
|
|
47
|
+
if re.match(r"(application|text)\/([^+]+\+)*json.*", media_type) is not None:
|
|
48
48
|
serialized_request_body.content = marshal_json(request_body, request_body_type)
|
|
49
49
|
elif re.match(r"multipart\/.*", media_type) is not None:
|
|
50
50
|
(
|