mangopay4-python-sdk 3.52.0__py2.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.
mangopay/base.py ADDED
@@ -0,0 +1,289 @@
1
+ from copy import deepcopy
2
+
3
+ import six
4
+
5
+ from . import get_default_handler
6
+ from .fields import PrimaryKeyField, FieldDescriptor, Field, ForeignRelatedObject
7
+ from .query import UpdateQuery, InsertQuery, SelectQuery, DeleteQuery
8
+ from .signals import pre_save, post_save
9
+ from .utils import force_text, force_str
10
+
11
+
12
+ class DoesNotExist(Exception):
13
+ pass
14
+
15
+
16
+ class BaseModelOptions(object):
17
+ def __init__(self, model_class, options=None):
18
+ self.rel_fields = {}
19
+ self.fields = {}
20
+ self.api_names = {}
21
+ self.options = options or {}
22
+ self.reverse_relations = {}
23
+ self.defaults = {}
24
+
25
+ for k, v in self.options.items():
26
+ setattr(self, k, v)
27
+
28
+ self.model_class = model_class
29
+
30
+ def get_sorted_fields(self):
31
+ return sorted(self.fields.items(), key=lambda k, v: (k == self.pk_name and 1 or 2, v._order))
32
+
33
+ def get_field_names(self):
34
+ return [f[0] for f in self.get_sorted_fields()]
35
+
36
+ def get_fields(self):
37
+ return [f[1] for f in self.get_sorted_fields()]
38
+
39
+ def get_field_by_name(self, name):
40
+ if name in self.fields:
41
+ return self.fields[name]
42
+ raise AttributeError('Field named %s not found' % name)
43
+
44
+ def __contains__(self, k):
45
+ return k in self.options
46
+
47
+ def __setitem__(self, k, value):
48
+ self.options[k] = value
49
+
50
+ def __delitem__(self, k):
51
+ if k not in self.options:
52
+ raise KeyError('%s does not exists' % k)
53
+
54
+ del self.options[k]
55
+
56
+ def prepared(self):
57
+ for field in self.fields.values():
58
+ if field.default is None:
59
+ continue
60
+
61
+ self.defaults[field] = field.default
62
+
63
+ def get_default_dict(self):
64
+ dd = {}
65
+ for field, default in self.defaults.items():
66
+ if callable(default):
67
+ dd[field.name] = default()
68
+ else:
69
+ dd[field.name] = default
70
+ return dd
71
+
72
+
73
+ class ApiObjectBase(type):
74
+ inheritable_options = ['verbose_name', 'verbose_name_plural']
75
+
76
+ def __new__(cls, name, bases, attrs):
77
+ super_new = super(ApiObjectBase, cls).__new__
78
+ parents = [b for b in bases if isinstance(b, ApiObjectBase)]
79
+
80
+ if not parents:
81
+ # If this isn't a subclass of Model, don't do anything special.
82
+ return super_new(cls, name, bases, attrs)
83
+
84
+ module = attrs.pop('__module__')
85
+ new_class = super_new(cls, name, bases, {'__module__': module})
86
+
87
+ meta_options = {}
88
+ meta = attrs.pop('Meta', None)
89
+ if meta:
90
+ meta_options.update((k, v) for k, v in meta.__dict__.items() if not k.startswith('_'))
91
+
92
+ if 'urls' not in meta_options:
93
+ meta_options['urls'] = {}
94
+
95
+ orig_primary_key = None
96
+
97
+ for b in bases:
98
+ if not hasattr(b, '_meta'):
99
+ continue
100
+
101
+ base_meta = getattr(b, '_meta')
102
+ for (k, v) in base_meta.__dict__.items():
103
+ if k in cls.inheritable_options and k not in meta_options:
104
+ meta_options[k] = v
105
+
106
+ for (k, attr) in b.__dict__.items():
107
+ if isinstance(attr, ForeignRelatedObject) and isinstance(getattr(attr, 'old_field'), Field):
108
+ attrs[k] = deepcopy(getattr(attr, 'old_field'))
109
+ if not isinstance(attr, FieldDescriptor) or attr in attrs:
110
+ continue
111
+
112
+ attrs[k] = deepcopy(attr.field)
113
+
114
+ if isinstance(attr.field, PrimaryKeyField) and not orig_primary_key:
115
+ orig_primary_key = deepcopy(attr.field)
116
+
117
+ cls = super(ApiObjectBase, cls).__new__(cls, name, bases, attrs)
118
+
119
+ _meta = BaseModelOptions(cls, meta_options)
120
+ cls._meta = _meta
121
+ cls._data = None
122
+
123
+ for name, attr in list(cls.__dict__.items()):
124
+ if not isinstance(attr, Field):
125
+ continue
126
+
127
+ attr.add_to_class(cls, name)
128
+ _meta.fields[attr.name] = attr
129
+ _meta.api_names[attr.api_name] = attr.name
130
+
131
+ if isinstance(attr, PrimaryKeyField):
132
+ orig_primary_key = attr
133
+
134
+ if orig_primary_key is not None:
135
+ _meta.pk_name = orig_primary_key.name
136
+
137
+ _meta.model_name = new_class.__name__
138
+
139
+ exception_class = type('%sDoesNotExist' % _meta.model_name, (DoesNotExist,), {})
140
+
141
+ cls.DoesNotExist = exception_class
142
+ cls._meta.prepared()
143
+
144
+ return cls
145
+
146
+ @six.add_metaclass(ApiObjectBase)
147
+ class BaseApiModelMethods(object):
148
+ def __init__(self, *args, **kwargs):
149
+ self._data = self._meta.get_default_dict()
150
+ self._handler = kwargs.pop('handler', None)
151
+
152
+ for k, v in kwargs.items():
153
+ setattr(self, k, v)
154
+
155
+ @property
156
+ def handler(self):
157
+ return self._handler or get_default_handler()
158
+
159
+ def __repr__(self):
160
+ try:
161
+ u = six.text_type(self)
162
+ except (UnicodeEncodeError, UnicodeDecodeError):
163
+ u = '[Bad Unicode data]'
164
+ return force_str('<%s: %s>' % (self.__class__.__name__, u))
165
+
166
+ def __str__(self):
167
+ if six.PY2 and hasattr(self, '__unicode__'):
168
+ return force_text(self).encode('utf-8')
169
+
170
+ return '%s object' % self.__class__.__name__
171
+
172
+ def __eq__(self, other):
173
+ return (other.__class__ == self.__class__ and
174
+ self.get_pk() and
175
+ other.get_pk() == self.get_pk())
176
+
177
+
178
+ class BaseApiModel(BaseApiModelMethods):
179
+
180
+ def __getattr__(self, name):
181
+ return object.__getattribute__(self, self._meta.api_names.get(name, name))
182
+
183
+ def __setattr__(self, name, value):
184
+ super(BaseApiModel, self).__setattr__(self._meta.api_names.get(name, name), value)
185
+
186
+ def fixed_kwargs(self):
187
+ return {}
188
+
189
+ def save(self, handler=None, cls=None, idempotency_key=None):
190
+ self._handler = handler or self.handler
191
+
192
+ field_dict = dict(self._data)
193
+ field_dict.update(self.get_field_dict())
194
+ field_dict.pop(self._meta.pk_name)
195
+
196
+ all_fields = self._meta.fields
197
+
198
+ if cls is None:
199
+ cls = self.__class__
200
+
201
+ created = False
202
+
203
+ pre_save.send(cls, instance=self)
204
+
205
+ if self.get_pk():
206
+ update = self.update(
207
+ self.get_pk(),
208
+ **field_dict
209
+ )
210
+ result = update.execute(self._handler)
211
+ else:
212
+ for k, v in all_fields.items():
213
+ if v.required is True and field_dict[v.name] is None:
214
+ raise ValueError('Missing mandatory field: ' + v.name)
215
+
216
+ insert = self.insert(idempotency_key=idempotency_key, **field_dict)
217
+ result = insert.execute(self._handler)
218
+
219
+ created = True
220
+
221
+ post_save.send(cls, instance=self, created=created)
222
+
223
+ for key, value in result.items():
224
+ setattr(self, key, value)
225
+
226
+ return result
227
+
228
+ @classmethod
229
+ def select(cls, *args, **kwargs):
230
+ return SelectQuery(cls, *args, **kwargs)
231
+
232
+ @classmethod
233
+ def create(cls, **query):
234
+ handler = query.pop('handler', get_default_handler())
235
+ inst = cls(**query)
236
+ inst.save(handler)
237
+ return inst
238
+
239
+ @classmethod
240
+ def update(cls, reference, **query):
241
+ return UpdateQuery(cls, reference, **query)
242
+
243
+ @classmethod
244
+ def insert(cls, idempotency_key, **query):
245
+ return InsertQuery(cls, idempotency_key=idempotency_key, **query)
246
+
247
+ @classmethod
248
+ def get(cls, *args, **kwargs):
249
+ return cls.select().get(*args, **kwargs)
250
+
251
+ def one(self, resource_model):
252
+ return resource_model.select().get(self.get_pk(),
253
+ resource_model=self.__class__,
254
+ handler=self.handler)
255
+
256
+ def list(self, resource_model, **kwargs):
257
+ return resource_model.select().list(self.get_pk(),
258
+ self.__class__,
259
+ handler=self.handler,
260
+ **kwargs)
261
+
262
+ @classmethod
263
+ def all(cls, *args, **kwargs):
264
+ return cls.select().all(*args, **kwargs)
265
+
266
+ @classmethod
267
+ def delete(cls, *args, **kwargs):
268
+ return DeleteQuery(cls, *args, **kwargs).execute()
269
+
270
+ def get_pk(self):
271
+ return getattr(self, self._meta.pk_name, None)
272
+
273
+ def get_pk_field(self):
274
+ return self._meta.fields[self._meta.pk_name]
275
+
276
+ def get_field_dict(self):
277
+ def get_field_val(field):
278
+ field_value = getattr(self, field.name)
279
+ if not self.get_pk() and field_value is None and field.default is not None:
280
+ if callable(field.default):
281
+ field_value = field.default()
282
+ else:
283
+ field_value = field.default
284
+ setattr(self, field.name, field_value)
285
+ return (field.name, field_value)
286
+
287
+ pairs = map(get_field_val, self._meta.fields.values())
288
+
289
+ return dict(pairs)
mangopay/compat.py ADDED
@@ -0,0 +1,16 @@
1
+ # This code belongs to https://github.com/django/django/blob/master/django/utils/encoding.py
2
+ import six
3
+
4
+
5
+ def python_2_unicode_compatible(klass):
6
+ """
7
+ A decorator that defines __unicode__ and __str__ methods under Python 2.
8
+ Under Python 3 it does nothing.
9
+
10
+ To support Python 2 and 3 with a single code base, define a __str__ method
11
+ returning text and apply this decorator to the class.
12
+ """
13
+ if six.PY2:
14
+ klass.__unicode__ = klass.__str__
15
+ klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
16
+ return klass