diff --git a/stripe/_encode.py b/stripe/_encode.py index 7c402cf52..5812e9766 100644 --- a/stripe/_encode.py +++ b/stripe/_encode.py @@ -158,6 +158,15 @@ def _api_encode( elif hasattr(value, "id"): yield (key, getattr(value, "id")) elif isinstance(value, list) or isinstance(value, tuple): + if not value: + # An empty list signals "clear this array field". Stripe's + # form-encoded API interprets `key=` (empty string) as a + # request to remove all previously set values, matching the + # documented workaround of passing "" instead of []. + # Without this, an empty list is silently dropped and the + # field is left unchanged. + # See https://github.com/stripe/stripe-python/issues/802 + yield (key, "") for i, sv in enumerate(value): # Always use indexed format for arrays encoded_key = "%s[%d]" % (key, i) diff --git a/tests/test_encode.py b/tests/test_encode.py index f8f036c8f..96d014131 100644 --- a/tests/test_encode.py +++ b/tests/test_encode.py @@ -116,3 +116,27 @@ def test_encode_mixed_nested_list_value(self): ("items[1][0]", 3), ("items[1][1]", 4), ] + + def test_encode_empty_list_yields_empty_string(self): + """An empty list must encode to (key, '') so the Stripe API clears the field. + + Regression test for https://github.com/stripe/stripe-python/issues/802 + + Before this fix, _api_encode({"blocked_categories": []}) yielded + nothing — the field was silently omitted from the request and the Stripe + API left the previously-set values untouched. The documented workaround + was to pass "" instead of [], which encodes to ("blocked_categories", ""). + The fix makes an empty list behave identically to that workaround. + """ + result = list(_api_encode({"blocked_categories": []})) + assert result == [("blocked_categories", "")], ( + "Empty list should encode to (key, '') to clear the field; " + f"got {result!r} instead" + ) + + def test_encode_empty_tuple_yields_empty_string(self): + """An empty tuple must encode to (key, '') just like an empty list.""" + result = list(_api_encode({"tags": ()})) + assert result == [("tags", "")], ( + f"Empty tuple should encode to (key, ''); got {result!r}" + )