Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion stripe/_credit_note_line_item.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._expandable_field import ExpandableField
from stripe._stripe_object import StripeObject
from typing import ClassVar, Dict, List, Optional
Expand Down Expand Up @@ -162,7 +163,7 @@ class TaxRateDetails(StripeObject):
"""
The cost of each unit of product being credited.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
Same as `unit_amount`, but contains a decimal value with at most 12 decimal places.
"""
Expand All @@ -171,3 +172,4 @@ class TaxRateDetails(StripeObject):
"pretax_credit_amounts": PretaxCreditAmount,
"taxes": Tax,
}
_field_encodings = {"unit_amount_decimal": "decimal_string"}
36 changes: 36 additions & 0 deletions stripe/_encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import datetime
import time
from collections import OrderedDict
from decimal import Decimal
from typing import Any, Dict, Generator, Mapping, Optional, Tuple, Union

This comment was marked as spam.



Expand Down Expand Up @@ -82,6 +83,38 @@ def _coerce_int64_string(value: Any, *, encode: bool) -> Any:
return value


def _coerce_decimal_string(value: Any, *, encode: bool) -> Any:
"""
Coerce a decimal_string value in either direction.

encode=True: Decimal/int/float → str (request serialization)
encode=False: str → Decimal (response hydration)
"""
if value is None:
return None

if encode:
if isinstance(value, list):
return [
str(v)
if isinstance(v, (Decimal, int, float))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this check is repeated twice. Seems like the list iteration should recurse into _coerce_decimal_string?

and not isinstance(v, bool)
else v
for v in value
]
if isinstance(value, (Decimal, int, float)) and not isinstance(
value, bool
):
return str(value)
return value
else:
if isinstance(value, list):
return [Decimal(v) if isinstance(v, str) else v for v in value]
if isinstance(value, str):
return Decimal(value)
return value


def _coerce_value(value: Any, schema: _SchemaNode) -> Any:
"""Coerce a single value according to its schema node."""
if value is None:
Expand All @@ -90,6 +123,9 @@ def _coerce_value(value: Any, schema: _SchemaNode) -> Any:
if schema == "int64_string":
return _coerce_int64_string(value, encode=True)

if schema == "decimal_string":
return _coerce_decimal_string(value, encode=True)

if isinstance(schema, dict):
# Nested object schema
if isinstance(value, list):
Expand Down
7 changes: 5 additions & 2 deletions stripe/_invoice_item.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._createable_api_resource import CreateableAPIResource
from stripe._deletable_api_resource import DeletableAPIResource
from stripe._expandable_field import ExpandableField
Expand Down Expand Up @@ -99,11 +100,12 @@ class PriceDetails(StripeObject):
"""
The type of the pricing details.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
The unit amount (in the `currency` specified) of the item which contains a decimal value with at most 12 decimal places.
"""
_inner_class_types = {"price_details": PriceDetails}
_field_encodings = {"unit_amount_decimal": "decimal_string"}

class ProrationDetails(StripeObject):
class DiscountAmount(StripeObject):
Expand Down Expand Up @@ -200,7 +202,7 @@ class DiscountAmount(StripeObject):
"""
Quantity of units for the invoice item in integer format, with any decimal precision truncated. For the item's full-precision decimal quantity, use `quantity_decimal`. This field will be deprecated in favor of `quantity_decimal` in a future version. If the invoice item is a proration, the quantity of the subscription that the proration was computed for.
"""
quantity_decimal: str
quantity_decimal: Decimal
"""
Non-negative decimal with at most 12 decimal places. The quantity of units for the invoice item.
"""
Expand Down Expand Up @@ -445,3 +447,4 @@ async def retrieve_async(
"pricing": Pricing,
"proration_details": ProrationDetails,
}
_field_encodings = {"quantity_decimal": "decimal_string"}
7 changes: 5 additions & 2 deletions stripe/_invoice_line_item.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._expandable_field import ExpandableField
from stripe._stripe_object import StripeObject
from stripe._updateable_api_resource import UpdateableAPIResource
Expand Down Expand Up @@ -175,11 +176,12 @@ class PriceDetails(StripeObject):
"""
The type of the pricing details.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
The unit amount (in the `currency` specified) of the item which contains a decimal value with at most 12 decimal places.
"""
_inner_class_types = {"price_details": PriceDetails}
_field_encodings = {"unit_amount_decimal": "decimal_string"}

class Tax(StripeObject):
class TaxRateDetails(StripeObject):
Expand Down Expand Up @@ -292,7 +294,7 @@ class TaxRateDetails(StripeObject):
"""
Quantity of units for the invoice line item in integer format, with any decimal precision truncated. For the line item's full-precision decimal quantity, use `quantity_decimal`. This field will be deprecated in favor of `quantity_decimal` in a future version. If the line item is a proration or subscription, the quantity of the subscription that the proration was computed for.
"""
quantity_decimal: Optional[str]
quantity_decimal: Optional[Decimal]
"""
Non-negative decimal with at most 12 decimal places. The quantity of units for the line item.
"""
Expand Down Expand Up @@ -360,3 +362,4 @@ async def modify_async(
"pricing": Pricing,
"taxes": Tax,
}
_field_encodings = {"quantity_decimal": "decimal_string"}
12 changes: 9 additions & 3 deletions stripe/_plan.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._createable_api_resource import CreateableAPIResource
from stripe._deletable_api_resource import DeletableAPIResource
from stripe._expandable_field import ExpandableField
Expand Down Expand Up @@ -44,22 +45,26 @@ class Tier(StripeObject):
"""
Price for the entire tier.
"""
flat_amount_decimal: Optional[str]
flat_amount_decimal: Optional[Decimal]
"""
Same as `flat_amount`, but contains a decimal value with at most 12 decimal places.
"""
unit_amount: Optional[int]
"""
Per unit price for units relevant to the tier.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
Same as `unit_amount`, but contains a decimal value with at most 12 decimal places.
"""
up_to: Optional[int]
"""
Up to and including to this quantity will be contained in the tier.
"""
_field_encodings = {
"flat_amount_decimal": "decimal_string",
"unit_amount_decimal": "decimal_string",
}

class TransformUsage(StripeObject):
divide_by: int
Expand All @@ -79,7 +84,7 @@ class TransformUsage(StripeObject):
"""
The unit amount in cents (or local equivalent) to be charged, represented as a whole integer if possible. Only set if `billing_scheme=per_unit`.
"""
amount_decimal: Optional[str]
amount_decimal: Optional[Decimal]
"""
The unit amount in cents (or local equivalent) to be charged, represented as a decimal string with at most 12 decimal places. Only set if `billing_scheme=per_unit`.
"""
Expand Down Expand Up @@ -373,3 +378,4 @@ async def retrieve_async(
return instance

_inner_class_types = {"tiers": Tier, "transform_usage": TransformUsage}
_field_encodings = {"amount_decimal": "decimal_string"}
23 changes: 17 additions & 6 deletions stripe/_price.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._createable_api_resource import CreateableAPIResource
from stripe._expandable_field import ExpandableField
from stripe._list_object import ListObject
Expand Down Expand Up @@ -66,22 +67,26 @@ class Tier(StripeObject):
"""
Price for the entire tier.
"""
flat_amount_decimal: Optional[str]
flat_amount_decimal: Optional[Decimal]
"""
Same as `flat_amount`, but contains a decimal value with at most 12 decimal places.
"""
unit_amount: Optional[int]
"""
Per unit price for units relevant to the tier.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
Same as `unit_amount`, but contains a decimal value with at most 12 decimal places.
"""
up_to: Optional[int]
"""
Up to and including to this quantity will be contained in the tier.
"""
_field_encodings = {
"flat_amount_decimal": "decimal_string",
"unit_amount_decimal": "decimal_string",
}

custom_unit_amount: Optional[CustomUnitAmount]
"""
Expand All @@ -101,14 +106,15 @@ class Tier(StripeObject):
"""
The unit amount in cents (or local equivalent) to be charged, represented as a whole integer if possible. Only set if `billing_scheme=per_unit`.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
The unit amount in cents (or local equivalent) to be charged, represented as a decimal string with at most 12 decimal places. Only set if `billing_scheme=per_unit`.
"""
_inner_class_types = {
"custom_unit_amount": CustomUnitAmount,
"tiers": Tier,
}
_field_encodings = {"unit_amount_decimal": "decimal_string"}

class CustomUnitAmount(StripeObject):
maximum: Optional[int]
Expand Down Expand Up @@ -151,22 +157,26 @@ class Tier(StripeObject):
"""
Price for the entire tier.
"""
flat_amount_decimal: Optional[str]
flat_amount_decimal: Optional[Decimal]
"""
Same as `flat_amount`, but contains a decimal value with at most 12 decimal places.
"""
unit_amount: Optional[int]
"""
Per unit price for units relevant to the tier.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
Same as `unit_amount`, but contains a decimal value with at most 12 decimal places.
"""
up_to: Optional[int]
"""
Up to and including to this quantity will be contained in the tier.
"""
_field_encodings = {
"flat_amount_decimal": "decimal_string",
"unit_amount_decimal": "decimal_string",
}

class TransformQuantity(StripeObject):
divide_by: int
Expand Down Expand Up @@ -262,7 +272,7 @@ class TransformQuantity(StripeObject):
"""
The unit amount in cents (or local equivalent) to be charged, represented as a whole integer if possible. Only set if `billing_scheme=per_unit`.
"""
unit_amount_decimal: Optional[str]
unit_amount_decimal: Optional[Decimal]
"""
The unit amount in cents (or local equivalent) to be charged, represented as a decimal string with at most 12 decimal places. Only set if `billing_scheme=per_unit`.
"""
Expand Down Expand Up @@ -434,3 +444,4 @@ async def search_auto_paging_iter_async(
"tiers": Tier,
"transform_quantity": TransformQuantity,
}
_field_encodings = {"unit_amount_decimal": "decimal_string"}
8 changes: 6 additions & 2 deletions stripe/_stripe_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
StripeStreamResponseAsync,
)
from stripe._encode import _encode_datetime # pyright: ignore
from stripe._encode import _coerce_int64_string # pyright: ignore
from stripe._encode import _coerce_int64_string, _coerce_decimal_string # pyright: ignore
from stripe._request_options import (
PERSISTENT_OPTIONS_KEYS,
extract_options_from_dict,
Expand Down Expand Up @@ -646,7 +646,8 @@ def _coerce_field_value(self, field_name: str, value: Any) -> Any:
Apply field encoding coercion based on _field_encodings metadata.

For int64_string fields, converts string values from the API response
to native Python ints.
to native Python ints. For decimal_string fields, converts string
values to decimal.Decimal.
"""
encoding = self._field_encodings.get(field_name)
if encoding is None or value is None:
Expand All @@ -655,4 +656,7 @@ def _coerce_field_value(self, field_name: str, value: Any) -> Any:
if encoding == "int64_string":
return _coerce_int64_string(value, encode=False)

if encoding == "decimal_string":
return _coerce_decimal_string(value, encode=False)

return value
4 changes: 3 additions & 1 deletion stripe/checkout/_session.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._createable_api_resource import CreateableAPIResource
from stripe._expandable_field import ExpandableField
from stripe._list_object import ListObject
Expand Down Expand Up @@ -286,14 +287,15 @@ class CurrencyConversion(StripeObject):
"""
Total of all items in source currency after discounts and taxes are applied.
"""
fx_rate: str
fx_rate: Decimal
"""
Exchange rate used to convert source currency amounts to customer currency amounts
"""
source_currency: str
"""
Creation currency of the CheckoutSession before localization
"""
_field_encodings = {"fx_rate": "decimal_string"}

class CustomField(StripeObject):
class Dropdown(StripeObject):
Expand Down
4 changes: 3 additions & 1 deletion stripe/climate/_order.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._createable_api_resource import CreateableAPIResource
from stripe._expandable_field import ExpandableField
from stripe._list_object import ListObject
Expand Down Expand Up @@ -152,7 +153,7 @@ class Location(StripeObject):
"""
Set of [key-value pairs](https://docs.stripe.com/api/metadata) that you can attach to an object. This can be useful for storing additional information about the object in a structured format.
"""
metric_tons: str
metric_tons: Decimal
"""
Quantity of carbon removal that is included in this order.
"""
Expand Down Expand Up @@ -435,3 +436,4 @@ async def retrieve_async(
"beneficiary": Beneficiary,
"delivery_details": DeliveryDetail,
}
_field_encodings = {"metric_tons": "decimal_string"}
4 changes: 3 additions & 1 deletion stripe/climate/_product.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# File generated from our OpenAPI spec
from decimal import Decimal
from stripe._list_object import ListObject
from stripe._listable_api_resource import ListableAPIResource
from stripe._stripe_object import StripeObject
Expand Down Expand Up @@ -58,7 +59,7 @@ class CurrentPricesPerMetricTon(StripeObject):
"""
Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
"""
metric_tons_available: str
metric_tons_available: Decimal
"""
The quantity of metric tons available for reservation.
"""
Expand Down Expand Up @@ -140,3 +141,4 @@ async def retrieve_async(
_inner_class_types = {
"current_prices_per_metric_ton": CurrentPricesPerMetricTon,
}
_field_encodings = {"metric_tons_available": "decimal_string"}
Loading
Loading