Skip to content

Commit 46c670a

Browse files
committed
Allow attributes to be deleted.
Before this commit, you could very easily get a Stripe object into an unsaveable state. Now you can fix yourself.
1 parent 9c8b89a commit 46c670a

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

stripe/resource.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ def __getattr__(self, k):
117117
except KeyError, err:
118118
raise AttributeError(*err.args)
119119

120+
def __delattr__(self, k):
121+
if k[0] == '_' or k in self.__dict__:
122+
return super(StripeObject, self).__delattr__(k)
123+
else:
124+
del self[k]
125+
120126
def __setitem__(self, k, v):
121127
if v == "":
122128
raise ValueError(
@@ -149,9 +155,11 @@ def __getitem__(self, k):
149155
raise err
150156

151157
def __delitem__(self, k):
152-
raise TypeError(
153-
"You cannot delete attributes on a StripeObject. "
154-
"To unset a property, set it to None.")
158+
super(StripeObject, self).__delitem__(k)
159+
160+
# Allows for unpickling in Python 3.x
161+
if hasattr(self, '_unsaved_values'):
162+
self._unsaved_values.remove(k)
155163

156164
@classmethod
157165
def construct_from(cls, values, key, stripe_account=None):

stripe/test/test_resources.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ def test_access(self):
5353

5454
# Illegal operations
5555
self.assertRaises(ValueError, setattr, obj, 'foo', '')
56-
self.assertRaises(TypeError, obj.__delitem__, 'myattr')
5756

5857
def test_refresh_from(self):
5958
obj = stripe.resource.StripeObject.construct_from({
@@ -163,6 +162,18 @@ def test_pickling(self):
163162
self.assertEqual('boo', newobj['object'])
164163
self.assertEqual('lalala', newobj.fala)
165164

165+
def test_deletion(self):
166+
obj = stripe.resource.StripeObject('id', 'key')
167+
168+
obj.coupon = "foo"
169+
self.assertEqual('foo', obj.coupon)
170+
171+
del obj.coupon
172+
self.assertRaises(AttributeError, getattr, obj, 'coupon')
173+
174+
obj.refresh_from({'coupon': 'foo'}, api_key='bar', partial=True)
175+
self.assertEqual('foo', obj.coupon)
176+
166177

167178
class ListObjectTests(StripeApiTestCase):
168179

@@ -1068,6 +1079,22 @@ def test_unset_description(self):
10681079
{'Idempotency-Key': 'foo'}
10691080
)
10701081

1082+
def test_del_coupon(self):
1083+
customer = stripe.Customer(id="cus_unset_desc")
1084+
customer.description = "bar"
1085+
customer.coupon = "foo"
1086+
del customer.coupon
1087+
customer.save()
1088+
1089+
self.requestor_mock.request.assert_called_with(
1090+
'post',
1091+
'/v1/customers/cus_unset_desc',
1092+
{
1093+
'description': 'bar'
1094+
},
1095+
None
1096+
)
1097+
10711098
def test_cannot_set_empty_string(self):
10721099
customer = stripe.Customer()
10731100
self.assertRaises(ValueError, setattr, customer, "description", "")

0 commit comments

Comments
 (0)