diff --git a/API_VERSION b/API_VERSION index 72fc940f3..fdbfbaad7 100644 --- a/API_VERSION +++ b/API_VERSION @@ -1 +1 @@ -a3035d6cb25cc44d50589c1da75b21abbd3601ca \ No newline at end of file +499f00588b1b41670a44a1e00598db81222ce169 \ No newline at end of file diff --git a/OPENAPI_VERSION b/OPENAPI_VERSION index abf60f206..02f8a7cef 100644 --- a/OPENAPI_VERSION +++ b/OPENAPI_VERSION @@ -1 +1 @@ -v2143 \ No newline at end of file +v2149 \ No newline at end of file diff --git a/stripe/_encode.py b/stripe/_encode.py index 228edfdc6..3d7e68ef1 100644 --- a/stripe/_encode.py +++ b/stripe/_encode.py @@ -31,8 +31,8 @@ def _api_encode(data) -> Generator[Tuple[str, Any], None, None]: for key, value in data.items(): if value is None: continue - elif hasattr(value, "stripe_id"): - yield (key, value.stripe_id) + elif hasattr(value, "id"): + yield (key, getattr(value, "id")) elif isinstance(value, list) or isinstance(value, tuple): for i, sv in enumerate(value): # Always use indexed format for arrays diff --git a/tests/test_encode.py b/tests/test_encode.py new file mode 100644 index 000000000..6aabc5c55 --- /dev/null +++ b/tests/test_encode.py @@ -0,0 +1,96 @@ +import warnings + +from stripe._stripe_object import StripeObject +from stripe._encode import _api_encode + + +class TestApiEncode: + def test_encode_stripe_object_without_id_no_deprecation_warning(self): + """ + Test that encoding a StripeObject without an id (like metadata) + does not trigger a deprecation warning. + Regression test for issue #1651. + """ + metadata = StripeObject() + metadata["key1"] = "value1" + metadata["key2"] = "value2" + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + result = list(_api_encode({"metadata": metadata})) + + # Check no deprecation warnings were raised + deprecation_warnings = [ + warning + for warning in w + if issubclass(warning.category, DeprecationWarning) + ] + assert len(deprecation_warnings) == 0, ( + f"Expected no deprecation warnings, but got {len(deprecation_warnings)}" + ) + + # Verify the metadata was encoded correctly as nested dict + assert result == [ + ("metadata[key1]", "value1"), + ("metadata[key2]", "value2"), + ] + + def test_encode_stripe_object_with_id_extracts_id(self): + """ + Test that encoding a StripeObject with an id (like a customer reference) + correctly extracts just the id value. + """ + customer = StripeObject() + customer["id"] = "cus_123" + customer["name"] = "Test Customer" + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + result = list(_api_encode({"customer": customer})) + + # Check no deprecation warnings were raised + deprecation_warnings = [ + warning + for warning in w + if issubclass(warning.category, DeprecationWarning) + ] + assert len(deprecation_warnings) == 0, ( + f"Expected no deprecation warnings, but got {len(deprecation_warnings)}" + ) + + # Should encode to just the ID + assert result == [("customer", "cus_123")] + + def test_encode_regular_dict(self): + """Test that regular dicts are encoded as nested dicts.""" + regular_dict = {"key1": "value1", "key2": "value2"} + result = list(_api_encode({"data": regular_dict})) + + assert result == [ + ("data[key1]", "value1"), + ("data[key2]", "value2"), + ] + + def test_encode_none_value_skipped(self): + """Test that None values are skipped during encoding.""" + result = list(_api_encode({"field": None})) + assert result == [] + + def test_encode_string_value(self): + """Test that string values are encoded directly.""" + result = list(_api_encode({"name": "John Doe"})) + assert result == [("name", "John Doe")] + + def test_encode_boolean_value(self): + """Test that boolean values are encoded as lowercase strings.""" + result = list(_api_encode({"active": True, "deleted": False})) + assert result == [("active", "true"), ("deleted", "false")] + + def test_encode_list_value(self): + """Test that list values are encoded with indexed keys.""" + result = list(_api_encode({"items": ["item1", "item2", "item3"]})) + assert result == [ + ("items[0]", "item1"), + ("items[1]", "item2"), + ("items[2]", "item3"), + ]