appier 1.31.4__py2.py3-none-any.whl → 1.32.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.
Files changed (81) hide show
  1. appier/__init__.py +333 -52
  2. appier/amqp.py +29 -30
  3. appier/api.py +214 -212
  4. appier/asgi.py +54 -55
  5. appier/async_neo.py +46 -35
  6. appier/async_old.py +55 -42
  7. appier/asynchronous.py +7 -13
  8. appier/base.py +1762 -1429
  9. appier/bus.py +51 -52
  10. appier/cache.py +99 -84
  11. appier/common.py +9 -11
  12. appier/component.py +17 -19
  13. appier/compress.py +25 -28
  14. appier/config.py +96 -73
  15. appier/controller.py +9 -15
  16. appier/crypt.py +25 -21
  17. appier/data.py +73 -57
  18. appier/defines.py +191 -226
  19. appier/exceptions.py +103 -63
  20. appier/execution.py +94 -88
  21. appier/export.py +90 -88
  22. appier/extra.py +6 -13
  23. appier/extra_neo.py +8 -11
  24. appier/extra_old.py +18 -16
  25. appier/geo.py +57 -47
  26. appier/git.py +101 -90
  27. appier/graph.py +23 -24
  28. appier/http.py +520 -398
  29. appier/legacy.py +373 -180
  30. appier/log.py +90 -97
  31. appier/meta.py +42 -42
  32. appier/mock.py +32 -34
  33. appier/model.py +793 -681
  34. appier/model_a.py +208 -183
  35. appier/mongo.py +183 -107
  36. appier/observer.py +39 -31
  37. appier/part.py +23 -24
  38. appier/preferences.py +44 -47
  39. appier/queuing.py +78 -96
  40. appier/redisdb.py +40 -35
  41. appier/request.py +227 -175
  42. appier/scheduler.py +13 -18
  43. appier/serialize.py +37 -31
  44. appier/session.py +161 -147
  45. appier/settings.py +2 -11
  46. appier/smtp.py +53 -49
  47. appier/storage.py +39 -33
  48. appier/structures.py +50 -45
  49. appier/test/__init__.py +2 -11
  50. appier/test/base.py +111 -108
  51. appier/test/cache.py +28 -35
  52. appier/test/config.py +10 -19
  53. appier/test/crypt.py +3 -12
  54. appier/test/data.py +3 -12
  55. appier/test/exceptions.py +8 -17
  56. appier/test/export.py +16 -33
  57. appier/test/graph.py +27 -60
  58. appier/test/http.py +42 -54
  59. appier/test/legacy.py +20 -30
  60. appier/test/log.py +14 -35
  61. appier/test/mock.py +27 -123
  62. appier/test/model.py +79 -91
  63. appier/test/part.py +5 -14
  64. appier/test/preferences.py +5 -13
  65. appier/test/queuing.py +29 -37
  66. appier/test/request.py +61 -73
  67. appier/test/serialize.py +12 -23
  68. appier/test/session.py +10 -19
  69. appier/test/smtp.py +8 -14
  70. appier/test/structures.py +20 -24
  71. appier/test/typesf.py +14 -28
  72. appier/test/util.py +480 -438
  73. appier/typesf.py +251 -171
  74. appier/util.py +578 -407
  75. appier/validation.py +280 -143
  76. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/METADATA +6 -1
  77. appier-1.32.0.dist-info/RECORD +86 -0
  78. appier-1.31.4.dist-info/RECORD +0 -86
  79. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/LICENSE +0 -0
  80. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/WHEEL +0 -0
  81. {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/top_level.txt +0 -0
appier/model.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Hive Appier Framework
5
- # Copyright (c) 2008-2022 Hive Solutions Lda.
5
+ # Copyright (c) 2008-2024 Hive Solutions Lda.
6
6
  #
7
7
  # This file is part of Hive Appier Framework.
8
8
  #
@@ -22,16 +22,7 @@
22
22
  __author__ = "João Magalhães <joamag@hive.pt>"
23
23
  """ The author(s) of the module """
24
24
 
25
- __version__ = "1.0.0"
26
- """ The version of the module """
27
-
28
- __revision__ = "$LastChangedRevision$"
29
- """ The revision number of the module """
30
-
31
- __date__ = "$LastChangedDate$"
32
- """ The last change date of the module """
33
-
34
- __copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
25
+ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
35
26
  """ The copyright for the module """
36
27
 
37
28
  __license__ = "Apache License, Version 2.0"
@@ -65,13 +56,14 @@ RE = lambda v: [i for i in v if not i == ""]
65
56
  empty element from the provided list values """
66
57
 
67
58
  BUILDERS = {
68
- legacy.UNICODE : lambda v: v.decode("utf-8") if\
69
- isinstance(v, legacy.BYTES) else legacy.UNICODE(v),
70
- list : lambda v: RE(v) if isinstance(v, list) else\
71
- (json.loads(v) if isinstance(v, legacy.UNICODE) else RE([v])),
72
- dict : lambda v: json.loads(v) if isinstance(v, legacy.UNICODE) else dict(v),
73
- bool : lambda v: v if isinstance(v, bool) else\
74
- not v in ("", "0", "false", "False")
59
+ legacy.UNICODE: lambda v: v.decode("utf-8")
60
+ if isinstance(v, legacy.BYTES)
61
+ else legacy.UNICODE(v),
62
+ list: lambda v: RE(v)
63
+ if isinstance(v, list)
64
+ else (json.loads(v) if isinstance(v, legacy.UNICODE) else RE([v])),
65
+ dict: lambda v: json.loads(v) if isinstance(v, legacy.UNICODE) else dict(v),
66
+ bool: lambda v: v if isinstance(v, bool) else not v in ("", "0", "false", "False"),
75
67
  }
76
68
  """ The map associating the various types with the
77
69
  custom builder functions to be used when applying
@@ -79,32 +71,37 @@ the types function, this is relevant for the built-in
79
71
  types that are meant to avoid using the default constructor """
80
72
 
81
73
  BUILDERS_META = dict(
82
- text = BUILDERS[legacy.UNICODE],
83
- country = BUILDERS[legacy.UNICODE],
84
- longtext = BUILDERS[legacy.UNICODE],
85
- map = BUILDERS[dict],
86
- longmap = BUILDERS[dict],
87
- date = lambda v: float(v),
88
- datetetime = lambda v: float(v),
89
- file = None
74
+ text=BUILDERS[legacy.UNICODE],
75
+ country=BUILDERS[legacy.UNICODE],
76
+ longtext=BUILDERS[legacy.UNICODE],
77
+ map=BUILDERS[dict],
78
+ longmap=BUILDERS[dict],
79
+ date=lambda v: float(v),
80
+ datetetime=lambda v: float(v),
81
+ file=None,
90
82
  )
91
83
  """ Map equivalent to the builders map but appliable
92
84
  for meta based type naming, this map should be used as
93
85
  an extension to the base builder map """
94
86
 
95
87
  METAS = dict(
96
- text = lambda v, d, c = None: v,
97
- enum = lambda v, d, c = None: d["enum"].get(v, None),
98
- list = lambda v, d, c = None:\
99
- json.dumps(v, ensure_ascii = False, cls = c._encoder() if c else None),
100
- map = lambda v, d, c = None:\
101
- json.dumps(v, ensure_ascii = False, cls = c._encoder() if c else None),
102
- longmap = lambda v, d, c = None:\
103
- json.dumps(v, ensure_ascii = False, cls = c._encoder() if c else None),
104
- date = lambda v, d, c = None:\
105
- datetime.datetime.utcfromtimestamp(float(v)).strftime("%d %b %Y"),
106
- datetime = lambda v, d, c = None:\
107
- datetime.datetime.utcfromtimestamp(float(v)).strftime("%d %b %Y %H:%M:%S")
88
+ text=lambda v, d, c=None: v,
89
+ enum=lambda v, d, c=None: d["enum"].get(v, None),
90
+ list=lambda v, d, c=None: json.dumps(
91
+ v, ensure_ascii=False, cls=c._encoder() if c else None
92
+ ),
93
+ map=lambda v, d, c=None: json.dumps(
94
+ v, ensure_ascii=False, cls=c._encoder() if c else None
95
+ ),
96
+ longmap=lambda v, d, c=None: json.dumps(
97
+ v, ensure_ascii=False, cls=c._encoder() if c else None
98
+ ),
99
+ date=lambda v, d, c=None: datetime.datetime.utcfromtimestamp(float(v)).strftime(
100
+ "%d %b %Y"
101
+ ),
102
+ datetime=lambda v, d, c=None: datetime.datetime.utcfromtimestamp(float(v)).strftime(
103
+ "%d %b %Y %H:%M:%S"
104
+ ),
108
105
  )
109
106
  """ The map that contains the various mapping functions
110
107
  for the meta types that may be described for a field under
@@ -112,13 +109,13 @@ the current model specification, the resulting value for
112
109
  each of these functions should preferably be a string """
113
110
 
114
111
  TYPE_DEFAULTS = {
115
- legacy.BYTES : None,
116
- legacy.UNICODE : None,
117
- int : None,
118
- float : None,
119
- bool : False,
120
- list : lambda: [],
121
- dict : lambda: {}
112
+ legacy.BYTES: None,
113
+ legacy.UNICODE: None,
114
+ int: None,
115
+ float: None,
116
+ bool: False,
117
+ list: lambda: [],
118
+ dict: lambda: {},
122
119
  }
123
120
  """ The default values to be set when a type
124
121
  conversion fails for the provided string value
@@ -126,82 +123,70 @@ the resulting value may be returned when a validation
126
123
  fails an so it must be used carefully """
127
124
 
128
125
  TYPE_META = {
129
- typesf.File : "file",
130
- typesf.Files : "files",
131
- typesf.Reference : "reference",
132
- typesf.References : "references",
133
- legacy.BYTES : "string",
134
- legacy.UNICODE : "string",
135
- int : "number",
136
- float : "float",
126
+ typesf.File: "file",
127
+ typesf.Files: "files",
128
+ typesf.Reference: "reference",
129
+ typesf.References: "references",
130
+ legacy.BYTES: "string",
131
+ legacy.UNICODE: "string",
132
+ int: "number",
133
+ float: "float",
137
134
  bool: "bool",
138
- list : "list",
139
- dict : "map"
135
+ list: "list",
136
+ dict: "map",
140
137
  }
141
138
  """ Dictionary that defines the default mapping for each
142
139
  of the base data types against the associated default meta
143
140
  values for each for them, these meta type values are going
144
141
  to be used mostly for presentation purposes """
145
142
 
146
- TYPE_REFERENCES = (
147
- typesf.Reference,
148
- typesf.References
149
- )
143
+ TYPE_REFERENCES = (typesf.Reference, typesf.References)
150
144
  """ The various data types that are considered to be references
151
145
  so that they are lazy loaded from the data source, these kind
152
146
  of types should be compliant to a common interface so that they
153
147
  may be used "blindly" from an external entity """
154
148
 
155
149
  REVERSE = dict(
156
- descending = "ascending",
157
- ascending = "descending",
150
+ descending="ascending",
151
+ ascending="descending",
158
152
  )
159
153
  """ The reverse order dictionary that maps a certain
160
154
  order direction (as a string) with the opposite one
161
155
  this may be used to "calculate" the reverse value """
162
156
 
163
- DIRTY_PARAMS = (
164
- "map",
165
- "rules",
166
- "meta",
167
- "build",
168
- "skip",
169
- "limit",
170
- "sort",
171
- "raise_e"
172
- )
157
+ DIRTY_PARAMS = ("map", "rules", "meta", "build", "skip", "limit", "sort", "raise_e")
173
158
  """ The set containing the complete set of parameter names for
174
159
  the parameters that are considered to be dirty and that should
175
160
  be cleaned from any query operation on the data source, otherwise
176
161
  serious consequences may occur """
177
162
 
178
163
  OPERATORS = {
179
- "eq" : None,
180
- "equals" : None,
181
- "ne" : "$ne",
182
- "not_equals" : "$ne",
183
- "in" : "$in",
184
- "nin" : "$nin",
185
- "not_in" : "$nin",
186
- "like" : "$regex",
187
- "likei" : "$regex",
188
- "llike" : "$regex",
189
- "llikei" : "$regex",
190
- "rlike" : "$regex",
191
- "rlikei" : "$regex",
192
- "gt" : "$gt",
193
- "greater" : "$gt",
194
- "gte" : "$gte",
195
- "greater_equal" : "$gte",
196
- "lt" : "$lt",
197
- "lesser" : "$lt",
198
- "lte" : "$lte",
199
- "lesser_equal" : "$lte",
200
- "null" : None,
201
- "is_null" : None,
202
- "not_null" : "$ne",
203
- "is_not_null" : "$ne",
204
- "contains" : "$all"
164
+ "eq": None,
165
+ "equals": None,
166
+ "ne": "$ne",
167
+ "not_equals": "$ne",
168
+ "in": "$in",
169
+ "nin": "$nin",
170
+ "not_in": "$nin",
171
+ "like": "$regex",
172
+ "likei": "$regex",
173
+ "llike": "$regex",
174
+ "llikei": "$regex",
175
+ "rlike": "$regex",
176
+ "rlikei": "$regex",
177
+ "gt": "$gt",
178
+ "greater": "$gt",
179
+ "gte": "$gte",
180
+ "greater_equal": "$gte",
181
+ "lt": "$lt",
182
+ "lesser": "$lt",
183
+ "lte": "$lte",
184
+ "lesser_equal": "$lte",
185
+ "null": None,
186
+ "is_null": None,
187
+ "not_null": "$ne",
188
+ "is_not_null": "$ne",
189
+ "contains": "$all",
205
190
  }
206
191
  """ The map containing the mapping association between the
207
192
  normalized version of the operators and the infra-structure
@@ -210,29 +195,25 @@ of the values don't have a valid mapping for this operations
210
195
  the operator must be ignored and not used explicitly """
211
196
 
212
197
  VALUE_METHODS = {
213
- "in" : lambda v, t: [t(v) for v in v.split(";")],
214
- "not_in" : lambda v, t: [t(v) for v in v.split(";")],
215
- "like" : lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + ".*$",
216
- "likei" : lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + ".*$",
217
- "llike" : lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + "$",
218
- "llikei" : lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + "$",
219
- "rlike" : lambda v, t: "^" + legacy.UNICODE(re.escape(v)) + ".*$",
220
- "rlikei" : lambda v, t: "^" + legacy.UNICODE(re.escape(v)) + ".*$",
221
- "null" : lambda v, t: None,
222
- "is_null" : lambda v, t: None,
223
- "not_null" : lambda v, t: None,
224
- "is_not_null" : lambda v, t: None,
225
- "contains" : lambda v, t: [t(v) for v in v.split(";")]
198
+ "in": lambda v, t: [t(v) for v in v.split(";")],
199
+ "not_in": lambda v, t: [t(v) for v in v.split(";")],
200
+ "like": lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + ".*$",
201
+ "likei": lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + ".*$",
202
+ "llike": lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + "$",
203
+ "llikei": lambda v, t: "^.*" + legacy.UNICODE(re.escape(v)) + "$",
204
+ "rlike": lambda v, t: "^" + legacy.UNICODE(re.escape(v)) + ".*$",
205
+ "rlikei": lambda v, t: "^" + legacy.UNICODE(re.escape(v)) + ".*$",
206
+ "null": lambda v, t: None,
207
+ "is_null": lambda v, t: None,
208
+ "not_null": lambda v, t: None,
209
+ "is_not_null": lambda v, t: None,
210
+ "contains": lambda v, t: [t(v) for v in v.split(";")],
226
211
  }
227
212
  """ Map that associates each of the normalized operations with
228
213
  an inline function that together with the data type maps the
229
214
  the base string based value into the target normalized value """
230
215
 
231
- INSENSITIVE = {
232
- "likei" : True,
233
- "llikei" : True,
234
- "rlikei" : True
235
- }
216
+ INSENSITIVE = {"likei": True, "llikei": True, "rlikei": True}
236
217
  """ The map that associates the various operators with the boolean
237
218
  values that define if an insensitive base search should be used
238
219
  instead of the "typical" sensitive search """
@@ -243,10 +224,12 @@ EXTRA_CLS = []
243
224
 
244
225
  if legacy.PYTHON_ASYNC_GEN:
245
226
  from . import model_a
227
+
246
228
  EXTRA_CLS.append(model_a.ModelAsync)
247
229
 
248
230
  BUILDERS.update(BUILDERS_META)
249
231
 
232
+
250
233
  class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
251
234
  """
252
235
  Abstract model class from which all the models should
@@ -273,61 +256,75 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
273
256
  instance.__dict__["ref"] = None
274
257
  return instance
275
258
 
276
- def __init__(self, model = None, **kwargs):
259
+ def __init__(self, model=None, **kwargs):
277
260
  fill = kwargs.pop("fill", True)
278
261
  model = model or {}
279
- if fill: model = self.__class__.fill(model)
262
+ if fill:
263
+ model = self.__class__.fill(model)
280
264
  self.__dict__["model"] = model
281
265
  self.__dict__["owner"] = common.base().APP or None
282
266
  self.__dict__["ref"] = kwargs.pop("ref", None)
283
- for name, value in kwargs.items(): setattr(self, name, value)
267
+ for name, value in kwargs.items():
268
+ setattr(self, name, value)
284
269
  for name, method in self.__class__._extra_methods:
285
- if legacy.PYTHON_3: bound_method = types.MethodType(method, self)
286
- else: bound_method = types.MethodType(method, self, self.__class__)
270
+ if legacy.PYTHON_3:
271
+ bound_method = types.MethodType(method, self)
272
+ else:
273
+ bound_method = types.MethodType(method, self, self.__class__)
287
274
  setattr(self, name, bound_method)
288
275
  observer.Observable.__init__(self)
289
276
 
290
277
  def __str__(self):
291
278
  cls = self.__class__
292
279
  default = cls.default()
293
- if not default: return cls._name()
294
- if not default in self.model: return cls._name()
280
+ if not default:
281
+ return cls._name()
282
+ if not default in self.model:
283
+ return cls._name()
295
284
  value = self.model[default]
296
- if value == None: value = ""
285
+ if value == None:
286
+ value = ""
297
287
  is_string = legacy.is_str(value)
298
288
  return value if is_string else str(value)
299
289
 
300
290
  def __unicode__(self):
301
291
  cls = self.__class__
302
292
  default = cls.default()
303
- if not default: return cls._name()
293
+ if not default:
294
+ return cls._name()
304
295
  value = self.model[default]
305
- if value == None: value = ""
296
+ if value == None:
297
+ value = ""
306
298
  is_unicode = legacy.is_unicode(value)
307
299
  return value if is_unicode else legacy.UNICODE(value)
308
300
 
309
301
  def __getattribute__(self, name):
310
302
  try:
311
303
  model = object.__getattribute__(self, "model")
312
- if name in model: return model[name]
313
- except AttributeError: pass
304
+ if name in model:
305
+ return model[name]
306
+ except AttributeError:
307
+ pass
314
308
  cls = object.__getattribute__(self, "__class__")
315
309
  definition = cls.definition()
316
- if name in definition: raise AttributeError(
317
- "attribute '%s' is not set" % name
318
- )
310
+ if name in definition:
311
+ raise AttributeError("attribute '%s' is not set" % name)
319
312
  return object.__getattribute__(self, name)
320
313
 
321
314
  def __setattr__(self, name, value):
322
315
  is_base = name in self.__dict__
323
- if is_base: self.__dict__[name] = value
324
- else: self.model[name] = value
316
+ if is_base:
317
+ self.__dict__[name] = value
318
+ else:
319
+ self.model[name] = value
325
320
 
326
321
  def __delattr__(self, name):
327
322
  try:
328
323
  model = object.__getattribute__(self, "model")
329
- if name in model: del model[name]
330
- except AttributeError: pass
324
+ if name in model:
325
+ del model[name]
326
+ except AttributeError:
327
+ pass
331
328
 
332
329
  def __len__(self):
333
330
  return self.model.__len__()
@@ -353,12 +350,12 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
353
350
  @classmethod
354
351
  def new(
355
352
  cls,
356
- model = None,
357
- form = True,
358
- safe = True,
359
- build = False,
360
- fill = True,
361
- new = True,
353
+ model=None,
354
+ form=True,
355
+ safe=True,
356
+ build=False,
357
+ fill=True,
358
+ new=True,
362
359
  **kwargs
363
360
  ):
364
361
  """
@@ -408,26 +405,24 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
408
405
  model and after the proper validations are performed on it.
409
406
  """
410
407
 
411
- if model == None: model = util.get_object() if form else dict(kwargs)
412
- if fill: model = cls.fill(model, safe = not new)
413
- instance = cls(fill = False)
414
- instance.apply(model, form = form, safe_a = safe)
415
- if build: cls.build(instance.model, map = False)
416
- if new: instance.assert_is_new()
408
+ if model == None:
409
+ model = util.get_object() if form else dict(kwargs)
410
+ if fill:
411
+ model = cls.fill(model, safe=not new)
412
+ instance = cls(fill=False)
413
+ instance.apply(model, form=form, safe_a=safe)
414
+ if build:
415
+ cls.build(instance.model, map=False)
416
+ if new:
417
+ instance.assert_is_new()
417
418
  return instance
418
419
 
419
420
  @classmethod
420
- def old(cls, model = None, form = True, safe = True, build = False):
421
- return cls.new(
422
- model = model,
423
- form = form,
424
- safe = safe,
425
- build = build,
426
- new = False
427
- )
421
+ def old(cls, model=None, form=True, safe=True, build=False):
422
+ return cls.new(model=model, form=form, safe=safe, build=build, new=False)
428
423
 
429
424
  @classmethod
430
- def wrap(cls, models, build = True, handler = None, **kwargs):
425
+ def wrap(cls, models, build=True, handler=None, **kwargs):
431
426
  """
432
427
  "Wraps" the provided sequence (or single set) of model based data into a
433
428
  sequence of models (or a single model) so that proper business logic may
@@ -460,166 +455,177 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
460
455
  """
461
456
 
462
457
  is_sequence = isinstance(models, (list, tuple))
463
- if not is_sequence: models = [models]
458
+ if not is_sequence:
459
+ models = [models]
464
460
  wrapping = []
465
461
  for model in models:
466
- if not isinstance(model, dict): continue
467
- _model = cls(model = model, **kwargs)
462
+ if not isinstance(model, dict):
463
+ continue
464
+ _model = cls(model=model, **kwargs)
468
465
  handler and handler(_model.model)
469
- build and cls.build(_model.model, map = False)
466
+ build and cls.build(_model.model, map=False)
470
467
  wrapping.append(_model)
471
- if is_sequence: return wrapping
472
- else: return wrapping[0] if wrapping else None
468
+ if is_sequence:
469
+ return wrapping
470
+ else:
471
+ return wrapping[0] if wrapping else None
473
472
 
474
473
  @classmethod
475
- def singleton(
476
- cls,
477
- model = None,
478
- form = True,
479
- safe = True,
480
- build = False,
481
- *args,
482
- **kwargs
483
- ):
484
- instance = cls.get(raise_e = False, *args, **kwargs)
474
+ def singleton(cls, model=None, form=True, safe=True, build=False, *args, **kwargs):
475
+ instance = cls.get(raise_e=False, *args, **kwargs)
485
476
  if instance:
486
- instance.apply(model, form = form, safe_a = safe)
477
+ instance.apply(model, form=form, safe_a=safe)
487
478
  else:
488
- instance = cls.old(
489
- model = model,
490
- form = form,
491
- safe = safe,
492
- build = build
493
- )
479
+ instance = cls.old(model=model, form=form, safe=safe, build=build)
494
480
  return instance
495
481
 
496
482
  @classmethod
497
483
  def get(cls, *args, **kwargs):
498
- fields,\
499
- eager,\
500
- eager_l,\
501
- map,\
502
- rules,\
503
- meta,\
504
- build,\
505
- fill,\
506
- resolve_a,\
507
- skip,\
508
- limit,\
509
- sort,\
510
- raise_e = cls._get_attrs(kwargs, (
511
- ("fields", None),
512
- ("eager", None),
513
- ("eager_l", None),
514
- ("map", False),
515
- ("rules", True),
516
- ("meta", False),
517
- ("build", True),
518
- ("fill", True),
519
- ("resolve_a", None),
520
- ("skip", 0),
521
- ("limit", 0),
522
- ("sort", None),
523
- ("raise_e", True)
524
- ))
484
+ (
485
+ fields,
486
+ eager,
487
+ eager_l,
488
+ map,
489
+ rules,
490
+ meta,
491
+ build,
492
+ fill,
493
+ resolve_a,
494
+ skip,
495
+ limit,
496
+ sort,
497
+ raise_e,
498
+ ) = cls._get_attrs(
499
+ kwargs,
500
+ (
501
+ ("fields", None),
502
+ ("eager", None),
503
+ ("eager_l", None),
504
+ ("map", False),
505
+ ("rules", True),
506
+ ("meta", False),
507
+ ("build", True),
508
+ ("fill", True),
509
+ ("resolve_a", None),
510
+ ("skip", 0),
511
+ ("limit", 0),
512
+ ("sort", None),
513
+ ("raise_e", True),
514
+ ),
515
+ )
525
516
 
526
517
  # in case there's a sort field and the safe search mode is enabled
527
518
  # we must add sorting by the `_id` field so that the retrieval is
528
519
  # considered to be deterministic, otherwise some DB implementations
529
520
  # will not respect the same sorting sequence across different calls
530
521
  if sort and (skip or limit):
531
- if not isinstance(sort, list): sort = list(sort)
522
+ if not isinstance(sort, list):
523
+ sort = list(sort)
532
524
  sort.append(["_id", 1])
533
525
 
534
- if eager_l == None: eager_l = map
535
- if resolve_a == None: resolve_a = map
536
- if eager_l: eager = cls._eager_b(eager)
537
- fields = cls._sniff(fields, rules = rules)
526
+ if eager_l == None:
527
+ eager_l = map
528
+ if resolve_a == None:
529
+ resolve_a = map
530
+ if eager_l:
531
+ eager = cls._eager_b(eager)
532
+ fields = cls._sniff(fields, rules=rules)
538
533
  collection = cls._collection()
539
- model = collection.find_one(
540
- kwargs,
541
- fields,
542
- skip = skip,
543
- limit = limit,
544
- sort = sort
545
- )
534
+ model = collection.find_one(kwargs, fields, skip=skip, limit=limit, sort=sort)
546
535
  if not model and raise_e:
547
536
  is_devel = common.is_devel()
548
- if is_devel: message = "%s not found for %s" % (cls.__name__, str(kwargs))
549
- else: message = "%s not found" % cls.__name__
550
- raise exceptions.NotFoundError(message = message)
551
- if not model and not raise_e: return model
537
+ if is_devel:
538
+ message = "%s not found for %s" % (cls.__name__, str(kwargs))
539
+ else:
540
+ message = "%s not found" % cls.__name__
541
+ raise exceptions.NotFoundError(message=message)
542
+ if not model and not raise_e:
543
+ return model
552
544
  cls.types(model)
553
- if fill: cls.fill(model, safe = rules)
554
- if build: cls.build(model, map = map, rules = rules, meta = meta)
555
- if eager: model = cls._eager(model, eager, map = map)
556
- if resolve_a: model = cls._resolve_all(model, resolve = False)
557
- return model if map else cls.old(model = model, safe = False)
545
+ if fill:
546
+ cls.fill(model, safe=rules)
547
+ if build:
548
+ cls.build(model, map=map, rules=rules, meta=meta)
549
+ if eager:
550
+ model = cls._eager(model, eager, map=map)
551
+ if resolve_a:
552
+ model = cls._resolve_all(model, resolve=False)
553
+ return model if map else cls.old(model=model, safe=False)
558
554
 
559
555
  @classmethod
560
556
  def find(cls, *args, **kwargs):
561
- fields,\
562
- eager,\
563
- eager_l,\
564
- map,\
565
- rules,\
566
- meta,\
567
- build,\
568
- fill,\
569
- resolve_a,\
570
- skip,\
571
- limit,\
572
- sort,\
573
- raise_e = cls._get_attrs(kwargs, (
574
- ("fields", None),
575
- ("eager", None),
576
- ("eager_l", False),
577
- ("map", False),
578
- ("rules", True),
579
- ("meta", False),
580
- ("build", True),
581
- ("fill", True),
582
- ("resolve_a", None),
583
- ("skip", 0),
584
- ("limit", 0),
585
- ("sort", None),
586
- ("raise_e", False)
587
- ))
557
+ (
558
+ fields,
559
+ eager,
560
+ eager_l,
561
+ map,
562
+ rules,
563
+ meta,
564
+ build,
565
+ fill,
566
+ resolve_a,
567
+ skip,
568
+ limit,
569
+ sort,
570
+ raise_e,
571
+ ) = cls._get_attrs(
572
+ kwargs,
573
+ (
574
+ ("fields", None),
575
+ ("eager", None),
576
+ ("eager_l", False),
577
+ ("map", False),
578
+ ("rules", True),
579
+ ("meta", False),
580
+ ("build", True),
581
+ ("fill", True),
582
+ ("resolve_a", None),
583
+ ("skip", 0),
584
+ ("limit", 0),
585
+ ("sort", None),
586
+ ("raise_e", False),
587
+ ),
588
+ )
588
589
 
589
590
  # in case there's a sort field and the safe search mode is enabled
590
591
  # we must add sorting by the `_id` field so that the search is
591
592
  # considered to be deterministic, otherwise some DB implementations
592
593
  # will not respect the same sorting sequence across different calls
593
594
  if sort and (skip or limit):
594
- if not isinstance(sort, list): sort = list(sort)
595
+ if not isinstance(sort, list):
596
+ sort = list(sort)
595
597
  sort.append(["_id", 1])
596
598
 
597
- if resolve_a == None: resolve_a = map
598
- if eager_l: eager = cls._eager_b(eager)
599
+ if resolve_a == None:
600
+ resolve_a = map
601
+ if eager_l:
602
+ eager = cls._eager_b(eager)
599
603
 
600
604
  cls._find_s(kwargs)
601
605
  cls._find_d(kwargs)
602
606
 
603
- fields = cls._sniff(fields, rules = rules)
607
+ fields = cls._sniff(fields, rules=rules)
604
608
  collection = cls._collection()
605
- models = collection.find(
606
- kwargs,
607
- fields,
608
- skip = skip,
609
- limit = limit,
610
- sort = sort
611
- )
609
+ models = collection.find(kwargs, fields, skip=skip, limit=limit, sort=sort)
612
610
  if not models and raise_e:
613
611
  is_devel = common.is_devel()
614
- if is_devel: message = "%s not found for %s" % (cls.__name__, str(kwargs))
615
- else: message = "%s not found" % cls.__name__
616
- raise exceptions.NotFoundError(message = message)
612
+ if is_devel:
613
+ message = "%s not found for %s" % (cls.__name__, str(kwargs))
614
+ else:
615
+ message = "%s not found" % cls.__name__
616
+ raise exceptions.NotFoundError(message=message)
617
617
  models = [cls.types(model) for model in models]
618
- if fill: models = [cls.fill(model, safe = rules) for model in models]
619
- if build: [cls.build(model, map = map, rules = rules, meta = meta) for model in models]
620
- if eager: models = cls._eager(models, eager, map = map)
621
- if resolve_a: models = [cls._resolve_all(model, resolve = False) for model in models]
622
- models = models if map else [cls.old(model = model, safe = False) for model in models]
618
+ if fill:
619
+ models = [cls.fill(model, safe=rules) for model in models]
620
+ if build:
621
+ [cls.build(model, map=map, rules=rules, meta=meta) for model in models]
622
+ if eager:
623
+ models = cls._eager(models, eager, map=map)
624
+ if resolve_a:
625
+ models = [cls._resolve_all(model, resolve=False) for model in models]
626
+ models = (
627
+ models if map else [cls.old(model=model, safe=False) for model in models]
628
+ )
623
629
  return models
624
630
 
625
631
  @classmethod
@@ -644,7 +650,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
644
650
  return result
645
651
 
646
652
  @classmethod
647
- def paginate(cls, skip = 0, limit = 1, *args, **kwargs):
653
+ def paginate(cls, skip=0, limit=1, *args, **kwargs):
648
654
  # retrieves the reference to the current global request in handling
649
655
  # this is going to be used for operations on the parameters
650
656
  request = common.base().get_request()
@@ -665,20 +671,22 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
665
671
  # calculates the proper size of the current page being requested
666
672
  # taking into account the total number of values and the limit
667
673
  size = total % limit if index == count else limit
668
- if size == 0 and total > 0: size = limit
669
- if total == 0: size = 0
674
+ if size == 0 and total > 0:
675
+ size = limit
676
+ if total == 0:
677
+ size = 0
670
678
 
671
679
  # creates the base structure for the page populating with the
672
680
  # base values that may be used for display of the page
673
681
  page = dict(
674
- count = count,
675
- index = index,
676
- start = skip + 1,
677
- end = skip + limit,
678
- size = size,
679
- total = total,
680
- sorter = request.params_f.get("sorter", None),
681
- direction = request.params_f.get("direction", "descending")
682
+ count=count,
683
+ index=index,
684
+ start=skip + 1,
685
+ end=skip + limit,
686
+ size=size,
687
+ total=total,
688
+ sorter=request.params_f.get("sorter", None),
689
+ direction=request.params_f.get("direction", "descending"),
682
690
  )
683
691
 
684
692
  def generate(**kwargs):
@@ -689,7 +697,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
689
697
  # creates a copy of the current definition of the parameters and for each
690
698
  # of the exclusion parameters removes it from the current structure
691
699
  params = dict(request.params_f)
692
- if "async" in params: del params["async"]
700
+ if "async" in params:
701
+ del params["async"]
693
702
 
694
703
  # retrieves the "special" sorter keyword based argument and the equivalent
695
704
  # values for the current page in handling, this values are going to be used
@@ -702,24 +711,31 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
702
711
  # verifies if the sorter value is defined in the arguments and if that's
703
712
  # the case verifies if it's the same as the current one if that the case
704
713
  # the direction must be reversed otherwise the default direction is set
705
- if sorter and sorter == _sorter: params["direction"] = reverse
706
- elif sorter: params["direction"] = "descending"
714
+ if sorter and sorter == _sorter:
715
+ params["direction"] = reverse
716
+ elif sorter:
717
+ params["direction"] = "descending"
707
718
 
708
719
  # "copies" the complete set of values from the provided keyword
709
720
  # based arguments into the parameters map, properly converting them
710
721
  # into the proper string value (avoiding possible problems)
711
- for key, value in kwargs.items(): params[key] = str(value)
722
+ for key, value in kwargs.items():
723
+ params[key] = str(value)
712
724
 
713
725
  # iterates over the complete set of parameters to be sent to linearize
714
726
  # them into a sequence of tuples ready to be converted into quoted string
715
727
  for key, value in params.items():
716
728
  is_list = isinstance(value, (list, tuple))
717
- if not is_list: value = [value]
718
- for _value in value: params_l.append((key, _value))
729
+ if not is_list:
730
+ value = [value]
731
+ for _value in value:
732
+ params_l.append((key, _value))
719
733
 
720
734
  # converts the multiple parameters to be used into a linear
721
735
  # quoted manner so they they may be used as query string values
722
- query = [util.quote(key) + "=" + util.quote(value) for key, value in params_l]
736
+ query = [
737
+ util.quote(key) + "=" + util.quote(value) for key, value in params_l
738
+ ]
723
739
  query = "&".join(query)
724
740
  return "?" + query if query else query
725
741
 
@@ -734,17 +750,22 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
734
750
  collection.remove(kwargs)
735
751
 
736
752
  @classmethod
737
- def ordered(cls, filter = dict):
753
+ def ordered(cls, filter=dict):
738
754
  is_sequence = isinstance(filter, (list, tuple))
739
- if not is_sequence: filter = (filter,)
755
+ if not is_sequence:
756
+ filter = (filter,)
740
757
 
741
758
  ordered = list(cls._ordered)
742
759
 
743
760
  for name, value in cls.__dict__.items():
744
- if name.startswith("_"): continue
745
- if not name == name.lower(): continue
746
- if not isinstance(value, filter): continue
747
- if name in ordered: continue
761
+ if name.startswith("_"):
762
+ continue
763
+ if not name == name.lower():
764
+ continue
765
+ if not isinstance(value, filter):
766
+ continue
767
+ if name in ordered:
768
+ continue
748
769
  ordered.append(name)
749
770
 
750
771
  return ordered
@@ -753,7 +774,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
753
774
  def methods(cls):
754
775
  # in case the methods are already "cached" in the current
755
776
  # class (fast retrieval) returns immediately
756
- if "_methods" in cls.__dict__: return cls._methods
777
+ if "_methods" in cls.__dict__:
778
+ return cls._methods
757
779
 
758
780
  # starts the list that will hold the various method names
759
781
  # for the class, note that this value will be ordered
@@ -769,12 +791,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
769
791
  # ordered set of attributes from it extending the retrieved methods
770
792
  # list with the value for each of the model levels
771
793
  for _cls in hierarchy:
772
- ordered = _cls.ordered(
773
- filter = (
774
- types.FunctionType,
775
- classmethod
776
- )
777
- )
794
+ ordered = _cls.ordered(filter=(types.FunctionType, classmethod))
778
795
  methods.extend(ordered)
779
796
 
780
797
  # saves the retrieved set of methods in the current model definition
@@ -786,7 +803,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
786
803
  def fields(cls):
787
804
  # in case the fields are already "cached" in the current
788
805
  # class (fast retrieval) returns immediately
789
- if "_fields" in cls.__dict__: return cls._fields
806
+ if "_fields" in cls.__dict__:
807
+ return cls._fields
790
808
 
791
809
  # starts the list that will hold the various field names
792
810
  # for the class, note that this value will be ordered
@@ -814,7 +832,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
814
832
  def definition(cls):
815
833
  # in case the definition is already "cached" in the current
816
834
  # class (fast retrieval) returns immediately
817
- if "_definition" in cls.__dict__: return cls._definition
835
+ if "_definition" in cls.__dict__:
836
+ return cls._definition
818
837
 
819
838
  # creates the map that will hold the complete definition of
820
839
  # the current model
@@ -830,14 +849,18 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
830
849
  # associated with its definition map
831
850
  for _cls in hierarchy:
832
851
  for name, value in _cls.__dict__.items():
833
- if name.startswith("_"): continue
834
- if not name == name.lower(): continue
835
- if not isinstance(value, dict): continue
836
- if name in definition: raise exceptions.OperationalError(
837
- message = "Duplicated attribute '%s' in '%s' hierarchy" %\
838
- (name, _cls.__name__),
839
- code = 412
840
- )
852
+ if name.startswith("_"):
853
+ continue
854
+ if not name == name.lower():
855
+ continue
856
+ if not isinstance(value, dict):
857
+ continue
858
+ if name in definition:
859
+ raise exceptions.OperationalError(
860
+ message="Duplicated attribute '%s' in '%s' hierarchy"
861
+ % (name, _cls.__name__),
862
+ code=412,
863
+ )
841
864
  definition[name] = value
842
865
 
843
866
  # sets the "default" definition for the based identifier
@@ -853,7 +876,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
853
876
  def definition_extended(cls):
854
877
  # in case the definition extended is already "cached" in the current
855
878
  # class (fast retrieval) returns immediately
856
- if "_definition_extended" in cls.__dict__: return cls._definition_extended
879
+ if "_definition_extended" in cls.__dict__:
880
+ return cls._definition_extended
857
881
 
858
882
  # retrieves the base definition dictionary and duplicated it adding
859
883
  # the element present in the set of extra definition (overridable on
@@ -870,7 +894,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
870
894
  def links(cls):
871
895
  # in case the links are already "cached" in the current
872
896
  # class (fast retrieval) returns immediately
873
- if "_links" in cls.__dict__: return cls._links
897
+ if "_links" in cls.__dict__:
898
+ return cls._links
874
899
 
875
900
  # creates the list that will hold the complete set of method
876
901
  # names for links type methods
@@ -885,7 +910,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
885
910
  # class hierarchy to determine the ones that are links
886
911
  for name in methods:
887
912
  method = getattr(cls, name)
888
- if not hasattr(method, "_link"): continue
913
+ if not hasattr(method, "_link"):
914
+ continue
889
915
  reference = hasattr(method, "__self__") and method.__self__
890
916
  is_instance = False if reference else True
891
917
  method._link["instance"] = is_instance
@@ -893,7 +919,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
893
919
 
894
920
  # sorts the various links taking into account the name of
895
921
  # the link, this is considered the pre-defined order
896
- links.sort(key = lambda item: item["name"])
922
+ links.sort(key=lambda item: item["name"])
897
923
 
898
924
  # saves the list of link method names defined under the current
899
925
  # class and then returns the contents of it to the caller method
@@ -904,7 +930,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
904
930
  def links_m(cls):
905
931
  # in case the links are already "cached" in the current
906
932
  # class (fast retrieval) returns immediately
907
- if "_links_m" in cls.__dict__: return cls._links_m
933
+ if "_links_m" in cls.__dict__:
934
+ return cls._links_m
908
935
 
909
936
  # creates the map that will hold the complete set of method
910
937
  # names for links type methods
@@ -919,7 +946,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
919
946
  # class hierarchy to determine the ones that are links
920
947
  for name in methods:
921
948
  method = getattr(cls, name)
922
- if not hasattr(method, "_link"): continue
949
+ if not hasattr(method, "_link"):
950
+ continue
923
951
  links_m[method.__name__] = method._link
924
952
 
925
953
  # saves the map of link method names defined under the current
@@ -936,7 +964,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
936
964
  def operations(cls):
937
965
  # in case the operations are already "cached" in the current
938
966
  # class (fast retrieval) returns immediately
939
- if "_operations" in cls.__dict__: return cls._operations
967
+ if "_operations" in cls.__dict__:
968
+ return cls._operations
940
969
 
941
970
  # creates the list that will hold the complete set of method
942
971
  # names for operations type methods
@@ -951,7 +980,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
951
980
  # class hierarchy to determine the ones that are operations
952
981
  for name in methods:
953
982
  method = getattr(cls, name)
954
- if not hasattr(method, "_operation"): continue
983
+ if not hasattr(method, "_operation"):
984
+ continue
955
985
  reference = hasattr(method, "__self__") and method.__self__
956
986
  is_instance = False if reference else True
957
987
  method._operation["instance"] = is_instance
@@ -959,7 +989,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
959
989
 
960
990
  # sorts the various operations taking into account the name of
961
991
  # the operation, this is considered the pre-defined order
962
- operations.sort(key = lambda item: item["name"])
992
+ operations.sort(key=lambda item: item["name"])
963
993
 
964
994
  # saves the list of operation method names defined under the current
965
995
  # class and then returns the contents of it to the caller method
@@ -970,7 +1000,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
970
1000
  def operations_m(cls):
971
1001
  # in case the operations are already "cached" in the current
972
1002
  # class (fast retrieval) returns immediately
973
- if "_operations_m" in cls.__dict__: return cls._operations_m
1003
+ if "_operations_m" in cls.__dict__:
1004
+ return cls._operations_m
974
1005
 
975
1006
  # creates the map that will hold the complete set of method
976
1007
  # names for operations type methods
@@ -985,7 +1016,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
985
1016
  # class hierarchy to determine the ones that are operations
986
1017
  for name in methods:
987
1018
  method = getattr(cls, name)
988
- if not hasattr(method, "_operation"): continue
1019
+ if not hasattr(method, "_operation"):
1020
+ continue
989
1021
  operations_m[method.__name__] = method._operation
990
1022
 
991
1023
  # saves the map of operation method names defined under the current
@@ -1002,7 +1034,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1002
1034
  def views(cls):
1003
1035
  # in case the views are already "cached" in the current
1004
1036
  # class (fast retrieval) returns immediately
1005
- if "_views" in cls.__dict__: return cls._views
1037
+ if "_views" in cls.__dict__:
1038
+ return cls._views
1006
1039
 
1007
1040
  # creates the list that will hold the complete set of method
1008
1041
  # names for views type methods
@@ -1017,7 +1050,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1017
1050
  # class hierarchy to determine the ones that are views
1018
1051
  for name in methods:
1019
1052
  method = getattr(cls, name)
1020
- if not hasattr(method, "_view"): continue
1053
+ if not hasattr(method, "_view"):
1054
+ continue
1021
1055
  reference = hasattr(method, "__self__") and method.__self__
1022
1056
  is_instance = False if reference else True
1023
1057
  method._view["instance"] = is_instance
@@ -1025,7 +1059,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1025
1059
 
1026
1060
  # sorts the various views taking into account the name of
1027
1061
  # the view, this is considered the pre-defined order
1028
- views.sort(key = lambda item: item["name"])
1062
+ views.sort(key=lambda item: item["name"])
1029
1063
 
1030
1064
  # saves the list of view method names defined under the current
1031
1065
  # class and then returns the contents of it to the caller method
@@ -1036,7 +1070,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1036
1070
  def views_m(cls):
1037
1071
  # in case the views are already "cached" in the current
1038
1072
  # class (fast retrieval) returns immediately
1039
- if "_views_m" in cls.__dict__: return cls._views_m
1073
+ if "_views_m" in cls.__dict__:
1074
+ return cls._views_m
1040
1075
 
1041
1076
  # creates the map that will hold the complete set of method
1042
1077
  # names for views type methods
@@ -1051,7 +1086,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1051
1086
  # class hierarchy to determine the ones that are views
1052
1087
  for name in methods:
1053
1088
  method = getattr(cls, name)
1054
- if not hasattr(method, "_view"): continue
1089
+ if not hasattr(method, "_view"):
1090
+ continue
1055
1091
  views_m[method.__name__] = method._view
1056
1092
 
1057
1093
  # saves the map of view method names defined under the current
@@ -1067,17 +1103,20 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1067
1103
  @classmethod
1068
1104
  def definition_n(cls, name):
1069
1105
  definition = cls.definition_extended()
1070
- if not name in definition: return {}
1106
+ if not name in definition:
1107
+ return {}
1071
1108
  return definition[name]
1072
1109
 
1073
1110
  @classmethod
1074
- def register(cls, lazy = False):
1075
- if lazy: return
1111
+ def register(cls, lazy=False):
1112
+ if lazy:
1113
+ return
1076
1114
  cls.setup()
1077
1115
 
1078
1116
  @classmethod
1079
- def unregister(cls, lazy = False):
1080
- if lazy: return
1117
+ def unregister(cls, lazy=False):
1118
+ if lazy:
1119
+ return
1081
1120
  cls.teardown()
1082
1121
 
1083
1122
  @classmethod
@@ -1120,9 +1159,11 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1120
1159
  definition = cls.definition()
1121
1160
  for name in names:
1122
1161
  value = definition.get(name, None)
1123
- if value == None: continue
1162
+ if value == None:
1163
+ continue
1124
1164
  is_private = value.get("private", False)
1125
- if is_private: continue
1165
+ if is_private:
1166
+ continue
1126
1167
  _names.append(name)
1127
1168
  return _names
1128
1169
 
@@ -1147,17 +1188,20 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1147
1188
  return {}
1148
1189
 
1149
1190
  @classmethod
1150
- def build(cls, model, map = False, rules = True, meta = False):
1151
- if rules: cls.rules(model, map)
1191
+ def build(cls, model, map=False, rules=True, meta=False):
1192
+ if rules:
1193
+ cls.rules(model, map)
1152
1194
  cls._build(model, map)
1153
- if meta: cls._meta(model, map)
1195
+ if meta:
1196
+ cls._meta(model, map)
1154
1197
 
1155
1198
  @classmethod
1156
1199
  def rules(cls, model, map):
1157
1200
  for name, _value in legacy.eager(model.items()):
1158
1201
  definition = cls.definition_n(name)
1159
1202
  is_private = definition.get("private", False)
1160
- if not is_private: continue
1203
+ if not is_private:
1204
+ continue
1161
1205
  del model[name]
1162
1206
 
1163
1207
  @classmethod
@@ -1165,15 +1209,18 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1165
1209
  definition = cls.definition()
1166
1210
 
1167
1211
  for name, value in legacy.eager(model.items()):
1168
- if name == "_id": continue
1169
- if value == None: continue
1170
- if not name in definition: continue
1212
+ if name == "_id":
1213
+ continue
1214
+ if value == None:
1215
+ continue
1216
+ if not name in definition:
1217
+ continue
1171
1218
  model[name] = cls.cast(name, value)
1172
1219
 
1173
1220
  return model
1174
1221
 
1175
1222
  @classmethod
1176
- def fill(cls, model = None, safe = False):
1223
+ def fill(cls, model=None, safe=False):
1177
1224
  """
1178
1225
  Fills the current model with the proper values so that
1179
1226
  no values are unset as this would violate the model definition
@@ -1193,12 +1240,16 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1193
1240
  model = model or dict()
1194
1241
  definition = cls.definition()
1195
1242
  for name, _definition in definition.items():
1196
- if name in model: continue
1197
- if name in ("_id",): continue
1243
+ if name in model:
1244
+ continue
1245
+ if name in ("_id",):
1246
+ continue
1198
1247
  private = _definition.get("private", False)
1199
1248
  increment = _definition.get("increment", False)
1200
- if private and safe: continue
1201
- if increment: continue
1249
+ if private and safe:
1250
+ continue
1251
+ if increment:
1252
+ continue
1202
1253
  if "initial" in _definition:
1203
1254
  initial = _definition["initial"]
1204
1255
  model[name] = initial
@@ -1211,17 +1262,20 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1211
1262
  return model
1212
1263
 
1213
1264
  @classmethod
1214
- def cast(cls, name, value, safe = True):
1265
+ def cast(cls, name, value, safe=True):
1215
1266
  definition = cls.definition()
1216
- if not name in definition: return value
1217
- if value == None: return value
1267
+ if not name in definition:
1268
+ return value
1269
+ if value == None:
1270
+ return value
1218
1271
  _definition = cls.definition_n(name)
1219
1272
  _type = _definition.get("type", legacy.UNICODE)
1220
1273
  builder = BUILDERS.get(_type, _type)
1221
1274
  try:
1222
1275
  return builder(value) if builder else value
1223
1276
  except Exception:
1224
- if not safe: raise
1277
+ if not safe:
1278
+ raise
1225
1279
  default = type_d(_type, None)
1226
1280
  default = _type._default() if hasattr(_type, "_default") else default
1227
1281
  return default
@@ -1260,12 +1314,13 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1260
1314
  # the value if there's success
1261
1315
  info = cls.definition_n(name)
1262
1316
  description = info.get("description", None)
1263
- if description: return description
1317
+ if description:
1318
+ return description
1264
1319
 
1265
1320
  # because there's no explicit description defined
1266
1321
  # runs the automatic underscore to readable conversion
1267
1322
  # and sets the value on the field info dictionary
1268
- description = util.underscore_to_readable(name, capitalize = True)
1323
+ description = util.underscore_to_readable(name, capitalize=True)
1269
1324
  info["description"] = description
1270
1325
  return description
1271
1326
 
@@ -1287,7 +1342,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1287
1342
  def all_parents(cls):
1288
1343
  # in case the all parents are already "cached" in the current
1289
1344
  # class (fast retrieval) returns immediately
1290
- if "_all_parents" in cls.__dict__: return cls._all_parents
1345
+ if "_all_parents" in cls.__dict__:
1346
+ return cls._all_parents
1291
1347
 
1292
1348
  # creates the list to hold the various parent
1293
1349
  # entity classes, populated recursively
@@ -1323,7 +1379,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1323
1379
  def hierarchy(cls):
1324
1380
  # in case the hierarchy are already "cached" in the current
1325
1381
  # class (fast retrieval) returns immediately
1326
- if "_hierarchy" in cls.__dict__: return cls._hierarchy
1382
+ if "_hierarchy" in cls.__dict__:
1383
+ return cls._hierarchy
1327
1384
 
1328
1385
  # retrieves the complete set of parents for the current class
1329
1386
  # and then adds the current class to it
@@ -1339,7 +1396,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1339
1396
  def increments(cls):
1340
1397
  # in case the increments are already "cached" in the current
1341
1398
  # class (fast retrieval) returns immediately
1342
- if "_increments" in cls.__dict__: return cls._increments
1399
+ if "_increments" in cls.__dict__:
1400
+ return cls._increments
1343
1401
 
1344
1402
  # creates the list that will hold the various names that are
1345
1403
  # meant to be automatically incremented
@@ -1354,7 +1412,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1354
1412
  for name in definition:
1355
1413
  _definition = cls.definition_n(name)
1356
1414
  is_increment = _definition.get("increment", False)
1357
- if not is_increment: continue
1415
+ if not is_increment:
1416
+ continue
1358
1417
  increments.append(name)
1359
1418
 
1360
1419
  # saves the increment list under the class and then
@@ -1366,7 +1425,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1366
1425
  def indexes(cls):
1367
1426
  # in case the indexes are already "cached" in the current
1368
1427
  # class (fast retrieval) returns immediately
1369
- if "_indexes" in cls.__dict__: return cls._indexes
1428
+ if "_indexes" in cls.__dict__:
1429
+ return cls._indexes
1370
1430
 
1371
1431
  # creates the list that will hold the various names that are
1372
1432
  # meant to be indexed in the data source
@@ -1381,7 +1441,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1381
1441
  for name in definition:
1382
1442
  _definition = cls.definition_n(name)
1383
1443
  direction = _definition.get("index", False)
1384
- if not direction: continue
1444
+ if not direction:
1445
+ continue
1385
1446
  indexes.append((name, direction))
1386
1447
 
1387
1448
  # saves the index list under the class and then
@@ -1393,7 +1454,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1393
1454
  def safes(cls):
1394
1455
  # in case the safes are already "cached" in the current
1395
1456
  # class (fast retrieval) returns immediately
1396
- if "_safes" in cls.__dict__: return cls._safes
1457
+ if "_safes" in cls.__dict__:
1458
+ return cls._safes
1397
1459
 
1398
1460
  # creates the list that will hold the various names that are
1399
1461
  # meant to be safe values in the data source, the underlying
@@ -1409,7 +1471,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1409
1471
  for name in definition:
1410
1472
  _definition = cls.definition_n(name)
1411
1473
  is_safe = _definition.get("safe", False)
1412
- if not is_safe: continue
1474
+ if not is_safe:
1475
+ continue
1413
1476
  safes.append(name)
1414
1477
 
1415
1478
  # saves the safes list under the class and then
@@ -1421,7 +1484,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1421
1484
  def immutables(cls):
1422
1485
  # in case the immutables are already "cached" in the current
1423
1486
  # class (fast retrieval) returns immediately
1424
- if "_immutables" in cls.__dict__: return cls._immutables
1487
+ if "_immutables" in cls.__dict__:
1488
+ return cls._immutables
1425
1489
 
1426
1490
  # creates the list that will hold the various names that are
1427
1491
  # meant to be immutable values in the data source
@@ -1436,7 +1500,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1436
1500
  for name in definition:
1437
1501
  _definition = cls.definition_n(name)
1438
1502
  is_immutable = _definition.get("immutable", False)
1439
- if not is_immutable: continue
1503
+ if not is_immutable:
1504
+ continue
1440
1505
  immutables.append(name)
1441
1506
 
1442
1507
  # saves the immutables list under the class and then
@@ -1448,7 +1513,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1448
1513
  def eagers(cls):
1449
1514
  # in case the eagers are already "cached" in the current
1450
1515
  # class (fast retrieval) returns immediately
1451
- if "_eagers" in cls.__dict__: return cls._eagers
1516
+ if "_eagers" in cls.__dict__:
1517
+ return cls._eagers
1452
1518
 
1453
1519
  # creates the list that will hold the various names that are
1454
1520
  # meant to be eager values in the data source
@@ -1463,7 +1529,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1463
1529
  for name in definition:
1464
1530
  _definition = cls.definition_n(name)
1465
1531
  is_eager = _definition.get("eager", False)
1466
- if not is_eager: continue
1532
+ if not is_eager:
1533
+ continue
1467
1534
  eagers.append(name)
1468
1535
 
1469
1536
  # saves the eagers list under the class and then
@@ -1475,7 +1542,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1475
1542
  def default(cls):
1476
1543
  # in case the default are already "cached" in the current
1477
1544
  # class (fast retrieval) returns immediately
1478
- if "_default" in cls.__dict__: return cls._default
1545
+ if "_default" in cls.__dict__:
1546
+ return cls._default
1479
1547
 
1480
1548
  # retrieves the complete hierarchy of the model to be used
1481
1549
  # for the retrieval of the lowest possible default value for
@@ -1496,7 +1564,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1496
1564
  # continues the loop, nothing to be done
1497
1565
  _definition = cls.definition_n(name)
1498
1566
  is_default = _definition.get("default", False)
1499
- if not is_default: continue
1567
+ if not is_default:
1568
+ continue
1500
1569
 
1501
1570
  # in case the default value is found sets its name in the
1502
1571
  # current default value and then breaks the loop
@@ -1505,7 +1574,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1505
1574
 
1506
1575
  # in case the default value has been found must break the external
1507
1576
  # loop as nothing else remains to be found
1508
- if default: break
1577
+ if default:
1578
+ break
1509
1579
 
1510
1580
  # saves the default value (name) under the class and then
1511
1581
  # returns the sequence to the caller method
@@ -1513,7 +1583,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1513
1583
  return default
1514
1584
 
1515
1585
  @classmethod
1516
- def filter_merge(cls, name, filter, kwargs, operator = None):
1586
+ def filter_merge(cls, name, filter, kwargs, operator=None):
1517
1587
  # retrieves a possible previous filter defined for the
1518
1588
  # provided name in case it does exist must concatenate
1519
1589
  # that previous value in a join statement according to
@@ -1531,9 +1601,12 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1531
1601
  # then deletes the current name reference in the arguments
1532
1602
  # and updates the name value to the and value
1533
1603
  filter_a = kwargs.get(operator, [])
1534
- if filter_p: filter = filter_a + [{name : filter}, {name : filter_p}]
1535
- else: filter = filter_a + [{name : filter}]
1536
- if name in kwargs: del kwargs[name]
1604
+ if filter_p:
1605
+ filter = filter_a + [{name: filter}, {name: filter_p}]
1606
+ else:
1607
+ filter = filter_a + [{name: filter}]
1608
+ if name in kwargs:
1609
+ del kwargs[name]
1537
1610
  name = operator
1538
1611
 
1539
1612
  # sets the currently defined filter structures in the keyword
@@ -1554,7 +1627,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1554
1627
 
1555
1628
  @classmethod
1556
1629
  def is_concrete(cls):
1557
- if not "is_abstract" in cls.__dict__: return True
1630
+ if not "is_abstract" in cls.__dict__:
1631
+ return True
1558
1632
  return not cls.is_abstract()
1559
1633
 
1560
1634
  @classmethod
@@ -1563,32 +1637,30 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1563
1637
 
1564
1638
  @classmethod
1565
1639
  def is_equal(cls, other):
1566
- if not cls._name() == other._name(): return False
1567
- if not cls.__name__ == other.__name__: return False
1640
+ if not cls._name() == other._name():
1641
+ return False
1642
+ if not cls.__name__ == other.__name__:
1643
+ return False
1568
1644
  return True
1569
1645
 
1570
1646
  @classmethod
1571
1647
  def assert_is_attached_g(cls):
1572
- if cls.is_attached(): return
1573
- raise exceptions.OperationalError(
1574
- message = "Model is not attached",
1575
- code = 412
1576
- )
1648
+ if cls.is_attached():
1649
+ return
1650
+ raise exceptions.OperationalError(message="Model is not attached", code=412)
1577
1651
 
1578
1652
  @classmethod
1579
1653
  def assert_is_concrete_g(cls):
1580
- if cls.is_concrete(): return
1581
- raise exceptions.OperationalError(
1582
- message = "Model is not concrete",
1583
- code = 412
1584
- )
1654
+ if cls.is_concrete():
1655
+ return
1656
+ raise exceptions.OperationalError(message="Model is not concrete", code=412)
1585
1657
 
1586
1658
  @classmethod
1587
1659
  def assert_is_child_g(cls, parent):
1588
- if cls.is_child(parent): return
1660
+ if cls.is_child(parent):
1661
+ return
1589
1662
  raise exceptions.OperationalError(
1590
- message = "Model is not child of %s" % parent,
1591
- code = 412
1663
+ message="Model is not child of %s" % parent, code=412
1592
1664
  )
1593
1665
 
1594
1666
  @classmethod
@@ -1596,7 +1668,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1596
1668
  pass
1597
1669
 
1598
1670
  @classmethod
1599
- def _meta(cls, model, map, safe = True):
1671
+ def _meta(cls, model, map, safe=True):
1600
1672
  # iterates over the complete set of keys and values for the
1601
1673
  # current model map to try to compute the associated meta value
1602
1674
  # for all of its attributes (should use some computation)
@@ -1605,8 +1677,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1605
1677
  # unset (none) or an unloaded reference, if that's the
1606
1678
  # case the value is considered "invalid" not to be encoded
1607
1679
  is_reference = isinstance(value, TYPE_REFERENCES)
1608
- is_invalid = value == None or\
1609
- (is_reference and not value.is_resolved())
1680
+ is_invalid = value == None or (is_reference and not value.is_resolved())
1610
1681
 
1611
1682
  # retrieves the definition for the current key in iteration
1612
1683
  # so that it's possible to apply the mapper
@@ -1623,10 +1694,13 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1623
1694
  # invalid calls the proper mapper function otherwise runs the
1624
1695
  # default (fallback) operation for meta retrieval
1625
1696
  try:
1626
- if mapper and not is_invalid: value = mapper(value, definition, cls)
1627
- else: value = value if is_invalid else legacy.UNICODE(value)
1697
+ if mapper and not is_invalid:
1698
+ value = mapper(value, definition, cls)
1699
+ else:
1700
+ value = value if is_invalid else legacy.UNICODE(value)
1628
1701
  except Exception:
1629
- if not safe: raise
1702
+ if not safe:
1703
+ raise
1630
1704
  value = None
1631
1705
 
1632
1706
  # sets the final meta value in the model, so that it may be
@@ -1634,14 +1708,16 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1634
1708
  model[key + "_meta"] = value
1635
1709
 
1636
1710
  @classmethod
1637
- def _sniff(cls, fields, rules = False):
1711
+ def _sniff(cls, fields, rules=False):
1638
1712
  fields = fields or cls.fields()
1639
1713
  fields = list(fields)
1640
- if not rules: return fields
1714
+ if not rules:
1715
+ return fields
1641
1716
  for field in list(fields):
1642
1717
  definition = cls.definition_n(field)
1643
1718
  is_private = definition.get("private", False)
1644
- if is_private: fields.remove(field)
1719
+ if is_private:
1720
+ fields.remove(field)
1645
1721
  return fields
1646
1722
 
1647
1723
  @classmethod
@@ -1650,7 +1726,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1650
1726
  type = definition.get("type", legacy.UNICODE)
1651
1727
  for cls in type.mro():
1652
1728
  base = TYPE_META.get(cls, None)
1653
- if base: break
1729
+ if base:
1730
+ break
1654
1731
  return definition.get("meta", base)
1655
1732
 
1656
1733
  @classmethod
@@ -1664,14 +1741,14 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1664
1741
  return encoder
1665
1742
 
1666
1743
  @classmethod
1667
- def _collection(cls, name = None):
1744
+ def _collection(cls, name=None):
1668
1745
  name = name or cls._name()
1669
1746
  adapter = cls._adapter()
1670
1747
  collection = adapter.collection(name)
1671
1748
  return collection
1672
1749
 
1673
1750
  @classmethod
1674
- def _collection_a(cls, name = None):
1751
+ def _collection_a(cls, name=None):
1675
1752
  name = name or cls._name()
1676
1753
  adapter = cls._adapter()
1677
1754
  collection = adapter.collection_a(name)
@@ -1686,18 +1763,18 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1686
1763
  return name
1687
1764
 
1688
1765
  @classmethod
1689
- def _under(cls, plural = True):
1690
- return cls._underscore(plural = plural)
1766
+ def _under(cls, plural=True):
1767
+ return cls._underscore(plural=plural)
1691
1768
 
1692
1769
  @classmethod
1693
- def _underscore(cls, plural = True):
1770
+ def _underscore(cls, plural=True):
1694
1771
  camel = cls._plural() if plural else cls._singular()
1695
1772
  return util.camel_to_underscore(camel)
1696
1773
 
1697
1774
  @classmethod
1698
- def _readable(cls, plural = False):
1775
+ def _readable(cls, plural=False):
1699
1776
  camel = cls._plural() if plural else cls._singular()
1700
- return util.camel_to_readable(camel, capitalize = True)
1777
+ return util.camel_to_readable(camel, capitalize=True)
1701
1778
 
1702
1779
  @classmethod
1703
1780
  def _singular(cls):
@@ -1730,7 +1807,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1730
1807
  # that's the case runs the recursive eager loading of names and
1731
1808
  # returns the resulting sequence to the caller method
1732
1809
  is_list = isinstance(model, (list, tuple))
1733
- if is_list: return [cls._eager(_model, names, *args, **kwargs) for _model in model]
1810
+ if is_list:
1811
+ return [cls._eager(_model, names, *args, **kwargs) for _model in model]
1734
1812
 
1735
1813
  # iterates over the complete set of names that are meant to be
1736
1814
  # eager loaded from the model and runs the "resolution" process
@@ -1739,9 +1817,14 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1739
1817
  _model = model
1740
1818
  for part in name.split("."):
1741
1819
  is_sequence = isinstance(_model, (list, tuple))
1742
- if is_sequence: _model = [cls._res(value, part, *args, **kwargs) for value in _model]
1743
- else: _model = cls._res(_model, part, *args, **kwargs)
1744
- if not _model: break
1820
+ if is_sequence:
1821
+ _model = [
1822
+ cls._res(value, part, *args, **kwargs) for value in _model
1823
+ ]
1824
+ else:
1825
+ _model = cls._res(_model, part, *args, **kwargs)
1826
+ if not _model:
1827
+ break
1745
1828
 
1746
1829
  # returns the resulting model to the caller method, most of the
1747
1830
  # times this model should have not been touched
@@ -1770,14 +1853,16 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1770
1853
 
1771
1854
  # in case the provided is not valid returns it (no resolution is
1772
1855
  # possible) otherwise gather the base value for resolution
1773
- if not model: return model
1856
+ if not model:
1857
+ return model
1774
1858
  value = model[part]
1775
1859
 
1776
1860
  # check the data type of the requested name for resolution
1777
1861
  # and in case it's not valid and not a reference returns it
1778
1862
  # immediately, no resolution to be performed
1779
1863
  is_reference = isinstance(value, TYPE_REFERENCES)
1780
- if not value and not is_reference: return value
1864
+ if not value and not is_reference:
1865
+ return value
1781
1866
 
1782
1867
  # in case the value is a reference type object then runs
1783
1868
  # the resolve operation effectively resolving the values
@@ -1785,12 +1870,14 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1785
1870
  # that this operation is going to respect the map vs. instance
1786
1871
  # kind of resolution process so the data type of the resulting
1787
1872
  # value is going to depend on that
1788
- if is_reference: value = value.resolve(eager_l = True, *args, **kwargs)
1873
+ if is_reference:
1874
+ value = value.resolve(eager_l=True, *args, **kwargs)
1789
1875
 
1790
1876
  # in case the map resolution process was requested an explicit
1791
1877
  # set of the resolved value is required (implicit resolution
1792
1878
  # using `resolve()`) is not enough to ensure proper type structure
1793
- if kwargs.get("map", False): model[part] = value
1879
+ if kwargs.get("map", False):
1880
+ model[part] = value
1794
1881
 
1795
1882
  # returns the "final" (possibly resolved) value to the caller method
1796
1883
  # ready to be used for possible merging processes
@@ -1814,7 +1901,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1814
1901
 
1815
1902
  # in case the provided name is a simple one this is a direct attribute
1816
1903
  # of the current class and the expected tuple is returned immediately
1817
- if not "." in name: return cls, name
1904
+ if not "." in name:
1905
+ return cls, name
1818
1906
 
1819
1907
  # splits the namespace recursive name and then iterates over the multiple
1820
1908
  # relation attributes to retrieve their respective targets
@@ -1844,9 +1932,10 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1844
1932
  return _attrs
1845
1933
 
1846
1934
  @classmethod
1847
- def _clean_attrs(cls, kwargs, dirty = DIRTY_PARAMS):
1935
+ def _clean_attrs(cls, kwargs, dirty=DIRTY_PARAMS):
1848
1936
  for key in dirty:
1849
- if not key in kwargs: continue
1937
+ if not key in kwargs:
1938
+ continue
1850
1939
  del kwargs[key]
1851
1940
 
1852
1941
  @classmethod
@@ -1878,7 +1967,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1878
1967
  # in case the find string is currently not defined in the
1879
1968
  # named arguments map returns immediately as nothing is
1880
1969
  # meant to be done on this method
1881
- if not "find_s" in kwargs: return
1970
+ if not "find_s" in kwargs:
1971
+ return
1882
1972
 
1883
1973
  # retrieves the find string into a local variable, then
1884
1974
  # removes the find string from the named arguments map
@@ -1892,7 +1982,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1892
1982
  # there's none returns immediately, as it's not possible
1893
1983
  # to proceed with the filter creation
1894
1984
  default = find_n or cls.default()
1895
- if not default: return
1985
+ if not default:
1986
+ return
1896
1987
 
1897
1988
  # constructs the proper right and left parts of the regex
1898
1989
  # that is going to be constructed for the matching of the
@@ -1911,11 +2002,13 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1911
2002
  # string the both sides wildcard regex is used for the
1912
2003
  # search otherwise the search value to be used is the
1913
2004
  # exact match of the value (required type conversion)
1914
- if default_t in legacy.STRINGS: find_v = {
1915
- "$regex" : right + re.escape(find_s) + left,
1916
- "$options": "i" if find_i else ""
1917
- }
1918
- else: find_v = default_t(find_s)
2005
+ if default_t in legacy.STRINGS:
2006
+ find_v = {
2007
+ "$regex": right + re.escape(find_s) + left,
2008
+ "$options": "i" if find_i else "",
2009
+ }
2010
+ else:
2011
+ find_v = default_t(find_s)
1919
2012
  except Exception:
1920
2013
  # in case there's an error in the conversion for
1921
2014
  # the target type value sets the search value as
@@ -1934,7 +2027,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1934
2027
  # in case the find definition is currently not defined in the
1935
2028
  # named arguments map returns immediately as nothing is
1936
2029
  # meant to be done on this method
1937
- if not "find_d" in kwargs: return
2030
+ if not "find_d" in kwargs:
2031
+ return
1938
2032
 
1939
2033
  # tries to retrieve the value of the operator that is going
1940
2034
  # to be used to "join" the multiple find parts (find values)
@@ -1950,7 +2044,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1950
2044
  # verifies that the data type for the find definition is a
1951
2045
  # valid sequence and in case its not converts it into one
1952
2046
  # so that it may be used in sequence valid logic
1953
- if not isinstance(find_d, list): find_d = [find_d]
2047
+ if not isinstance(find_d, list):
2048
+ find_d = [find_d]
1954
2049
 
1955
2050
  # iterates over all the filters defined in the filter definition
1956
2051
  # so that they may be used to update the provided arguments with
@@ -1958,13 +2053,15 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1958
2053
  for filter in find_d:
1959
2054
  # in case the filter is not valid (unset or invalid) it's going
1960
2055
  # to be ignored as no valid information is present
1961
- if not filter: continue
2056
+ if not filter:
2057
+ continue
1962
2058
 
1963
2059
  # splits the filter string into its three main components
1964
2060
  # the name, operator and value, that are going to be processed
1965
2061
  # as defined by the specification to create the filter
1966
2062
  result = filter.split(":", 2)
1967
- if len(result) == 2: result.append(None)
2063
+ if len(result) == 2:
2064
+ result.append(None)
1968
2065
  name, operator, value = result
1969
2066
 
1970
2067
  # retrieves the definition for the filter attribute and uses
@@ -1973,8 +2070,10 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1973
2070
  # type resolution method exists it's used (recursive resolution)
1974
2071
  definition = cls.definition_n(name)
1975
2072
  name_t = definition.get("type", legacy.UNICODE)
1976
- if hasattr(name_t, "_btype"): name_t = name_t._btype()
1977
- if name in ("_id",): name_t = cls._adapter().object_id
2073
+ if hasattr(name_t, "_btype"):
2074
+ name_t = name_t._btype()
2075
+ if name in ("_id",):
2076
+ name_t = cls._adapter().object_id
1978
2077
 
1979
2078
  # determines if the current filter operation should be performed
1980
2079
  # using a case insensitive based approach to the search, by default
@@ -1990,21 +2089,25 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
1990
2089
  # in case there's a custom value mapped retrieved uses it to convert
1991
2090
  # the string based value into the target specific value for the query
1992
2091
  # otherwise uses the data type for the search field for value conversion
1993
- if value_method: value = value_method(value, name_t)
2092
+ if value_method:
2093
+ value = value_method(value, name_t)
1994
2094
  else:
1995
- try: value = name_t(value)
1996
- except ValueError: value = None
2095
+ try:
2096
+ value = name_t(value)
2097
+ except ValueError:
2098
+ value = None
1997
2099
 
1998
2100
  # constructs the custom find value using a key and value map value
1999
2101
  # in case the operator is defined otherwise (operator not defined)
2000
2102
  # the value is used directly, then merges this find value into the
2001
2103
  # current set of filters for the provided (keyword) arguments
2002
- find_v = {operator : value} if operator else value
2003
- if insensitive: find_v["$options"] = "i"
2004
- cls.filter_merge(name, find_v, kwargs, operator = find_o)
2104
+ find_v = {operator: value} if operator else value
2105
+ if insensitive:
2106
+ find_v["$options"] = "i"
2107
+ cls.filter_merge(name, find_v, kwargs, operator=find_o)
2005
2108
 
2006
2109
  @classmethod
2007
- def _bases(cls, subclass = None):
2110
+ def _bases(cls, subclass=None):
2008
2111
  """
2009
2112
  Retrieves the complete set of base (parent) classes for
2010
2113
  the current class, this method is safe as it removes any
@@ -2034,8 +2137,10 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2034
2137
  # according to their inheritance from the provided
2035
2138
  # (model) class to be applied as filter
2036
2139
  bases = cls.__bases__
2037
- if subclass: bases = [base for base in bases if issubclass(base, subclass)]
2038
- if not bases == Model.__bases__: return bases
2140
+ if subclass:
2141
+ bases = [base for base in bases if issubclass(base, subclass)]
2142
+ if not bases == Model.__bases__:
2143
+ return bases
2039
2144
 
2040
2145
  # returns an empty tuple to the caller method as the
2041
2146
  # top level class has been reached and the class is
@@ -2045,43 +2150,21 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2045
2150
  @classmethod
2046
2151
  def _increment(cls, name):
2047
2152
  _name = cls._name() + ":" + name
2048
- store = cls._collection(name = "counters")
2153
+ store = cls._collection(name="counters")
2049
2154
  value = store.find_and_modify(
2050
- {
2051
- "_id" : _name
2052
- },
2053
- {
2054
- "$inc" : {
2055
- "seq" : 1
2056
- }
2057
- },
2058
- new = True,
2059
- upsert = True
2155
+ {"_id": _name}, {"$inc": {"seq": 1}}, new=True, upsert=True
2060
2156
  )
2061
- value = value or store.find_one({
2062
- "_id" : _name
2063
- })
2157
+ value = value or store.find_one({"_id": _name})
2064
2158
  return value["seq"]
2065
2159
 
2066
2160
  @classmethod
2067
2161
  def _ensure_min(cls, name, value):
2068
2162
  _name = cls._name() + ":" + name
2069
- store = cls._collection(name = "counters")
2163
+ store = cls._collection(name="counters")
2070
2164
  value = store.find_and_modify(
2071
- {
2072
- "_id" : _name
2073
- },
2074
- {
2075
- "$max" : {
2076
- "seq" : value
2077
- }
2078
- },
2079
- new = True,
2080
- upsert = True
2165
+ {"_id": _name}, {"$max": {"seq": value}}, new=True, upsert=True
2081
2166
  )
2082
- value = value or store.find_one({
2083
- "_id" : _name
2084
- })
2167
+ value = value or store.find_one({"_id": _name})
2085
2168
  return value["seq"]
2086
2169
 
2087
2170
  @classmethod
@@ -2089,7 +2172,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2089
2172
  indexes = cls.indexes()
2090
2173
  collection = cls._collection()
2091
2174
  for index, direction in indexes:
2092
- collection.ensure_index(index, direction = direction)
2175
+ collection.ensure_index(index, direction=direction)
2093
2176
 
2094
2177
  @classmethod
2095
2178
  def _destroy_indexes(cls):
@@ -2117,7 +2200,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2117
2200
  eager = list(eager) if eager else []
2118
2201
  eagers = cls.eagers()
2119
2202
  eager.extend(eagers)
2120
- if not eager: return eager
2203
+ if not eager:
2204
+ return eager
2121
2205
  eager = tuple(set(eager))
2122
2206
  return eager
2123
2207
 
@@ -2125,7 +2209,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2125
2209
  def _resolve_all(cls, model, *args, **kwargs):
2126
2210
  definition = cls.definition()
2127
2211
  for name, value in legacy.eager(model.items()):
2128
- if not name in definition: continue
2212
+ if not name in definition:
2213
+ continue
2129
2214
  model[name] = cls._resolve(name, value, *args, **kwargs)
2130
2215
  return model
2131
2216
 
@@ -2135,7 +2220,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2135
2220
  # it is runs the evaluate method for each of the values to
2136
2221
  # try to resolve them into the proper representation
2137
2222
  is_iterable = isinstance(value, (list, tuple))
2138
- if is_iterable: return [cls._resolve(name, value, *args, **kwargs) for value in value]
2223
+ if is_iterable:
2224
+ return [cls._resolve(name, value, *args, **kwargs) for value in value]
2139
2225
 
2140
2226
  # in case the current instance is a dictionary then, and in case
2141
2227
  # there's a target class (typical for reference like types) recursion
@@ -2145,24 +2231,28 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2145
2231
  if isinstance(value, dict):
2146
2232
  info = getattr(cls, name)
2147
2233
  part_type = info.get("type", None)
2148
- if hasattr(part_type, "_target") :
2234
+ if hasattr(part_type, "_target"):
2149
2235
  _cls = part_type._target()
2150
2236
  return _cls._resolve_all(value, *args, **kwargs)
2151
2237
 
2152
2238
  # verifies if the map value recursive approach should be used
2153
2239
  # for the element and if that's the case calls the proper method
2154
2240
  # otherwise uses the provided (raw value)
2155
- if not hasattr(value, "map_v"): return value
2241
+ if not hasattr(value, "map_v"):
2242
+ return value
2156
2243
  return value.map_v(*args, **kwargs)
2157
2244
 
2158
2245
  @classmethod
2159
2246
  def _to_meta(cls, base):
2160
- if isinstance(base, str): return base
2247
+ if isinstance(base, str):
2248
+ return base
2161
2249
  is_class = inspect.isclass(type)
2162
- if not is_class: base = base.__class__
2250
+ if not is_class:
2251
+ base = base.__class__
2163
2252
  for cls in base.mro():
2164
2253
  result = TYPE_META.get(cls, None)
2165
- if not result: continue
2254
+ if not result:
2255
+ continue
2166
2256
  return result
2167
2257
  return base
2168
2258
 
@@ -2176,10 +2266,12 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2176
2266
 
2177
2267
  @property
2178
2268
  def logger(self):
2179
- if self.owner: return self.owner.logger
2180
- else: return logging.getLogger()
2269
+ if self.owner:
2270
+ return self.owner.logger
2271
+ else:
2272
+ return logging.getLogger()
2181
2273
 
2182
- def val(self, name, default = None):
2274
+ def val(self, name, default=None):
2183
2275
  return self.model.get(name, default)
2184
2276
 
2185
2277
  def json_v(self, *args, **kwargs):
@@ -2190,15 +2282,13 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2190
2282
  clone = kwargs.pop("clone", False)
2191
2283
  resolve = kwargs.get("resolve", True)
2192
2284
  evaluator = kwargs.get("evaluator", "map_v")
2193
- if clone: base = self.clone(reset = False, deep = True)
2194
- else: base = self
2195
- return cls._resolve_all(
2196
- base.model,
2197
- resolve = resolve,
2198
- evaluator = evaluator
2199
- )
2285
+ if clone:
2286
+ base = self.clone(reset=False, deep=True)
2287
+ else:
2288
+ base = self
2289
+ return cls._resolve_all(base.model, resolve=resolve, evaluator=evaluator)
2200
2290
 
2201
- def build_m(self, model = None, rules = True):
2291
+ def build_m(self, model=None, rules=True):
2202
2292
  """
2203
2293
  Builds the currently defined model, this should run
2204
2294
  additional computation for the current model creating
@@ -2222,9 +2312,9 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2222
2312
 
2223
2313
  cls = self.__class__
2224
2314
  model = model or self.model
2225
- cls.build(model, rules = rules)
2315
+ cls.build(model, rules=rules)
2226
2316
 
2227
- def apply(self, model = None, form = True, safe = None, safe_a = True):
2317
+ def apply(self, model=None, form=True, safe=None, safe_a=True):
2228
2318
  # calls the complete set of event handlers for the current
2229
2319
  # apply operation, this should trigger changes in the model
2230
2320
  self.pre_apply()
@@ -2241,16 +2331,19 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2241
2331
  # to the current map of safe attributes
2242
2332
  if safe_a:
2243
2333
  safes = cls.safes()
2244
- for _safe in safes: safe[_safe] = True
2334
+ for _safe in safes:
2335
+ safe[_safe] = True
2245
2336
 
2246
2337
  # retrieves the object loading it from all the available
2247
2338
  # sources and then iterates over all the of the model
2248
2339
  # values setting the values in the current instance's model
2249
2340
  # then runs the type casting/conversion operation in it
2250
- if model == None: model = util.get_object() if form else dict()
2341
+ if model == None:
2342
+ model = util.get_object() if form else dict()
2251
2343
  for name, value in legacy.eager(model.items()):
2252
2344
  is_safe = safe.get(name, False)
2253
- if is_safe: continue
2345
+ if is_safe:
2346
+ continue
2254
2347
  self.model[name] = value
2255
2348
  cls = self.__class__
2256
2349
  cls.types(self.model)
@@ -2263,22 +2356,24 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2263
2356
  # operation, this may be used for chaining operations
2264
2357
  return self
2265
2358
 
2266
- def copy(self, build = False, rules = True):
2359
+ def copy(self, build=False, rules=True):
2267
2360
  cls = self.__class__
2268
2361
  _copy = copy.deepcopy(self)
2269
- build and cls.build(_copy.model, map = False, rules = rules)
2362
+ build and cls.build(_copy.model, map=False, rules=rules)
2270
2363
  return _copy
2271
2364
 
2272
- def clone(self, reset = True, deep = False):
2365
+ def clone(self, reset=True, deep=False):
2273
2366
  cls = self.__class__
2274
2367
  model = dict(self.model) if deep else self.model
2275
- if not reset: return cls(model = model)
2368
+ if not reset:
2369
+ return cls(model=model)
2276
2370
  indexes = cls.increments()
2277
2371
  indexes = indexes + cls.unique_names() + ["_id"]
2278
2372
  for index in indexes:
2279
- if not index in model: continue
2373
+ if not index in model:
2374
+ continue
2280
2375
  del model[index]
2281
- return cls(model = model)
2376
+ return cls(model=model)
2282
2377
 
2283
2378
  def validate_extra(self, name):
2284
2379
  """
@@ -2314,10 +2409,10 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2314
2409
  be returned to the caller method until catching of exception.
2315
2410
  """
2316
2411
 
2317
- if self.is_new(): return
2412
+ if self.is_new():
2413
+ return
2318
2414
  raise exceptions.OperationalError(
2319
- message = "Instance is not new, identifier is set",
2320
- code = 412
2415
+ message="Instance is not new, identifier is set", code=412
2321
2416
  )
2322
2417
 
2323
2418
  def assert_is_attached(self):
@@ -2334,47 +2429,53 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2334
2429
 
2335
2430
  def save(
2336
2431
  self,
2337
- validate = True,
2338
- verify = True,
2339
- is_new = None,
2340
- increment_a = None,
2341
- immutables_a = None,
2342
- pre_validate = True,
2343
- pre_save = True,
2344
- pre_create = True,
2345
- pre_update = True,
2346
- post_validate = True,
2347
- post_save = True,
2348
- post_create = True,
2349
- post_update = True,
2350
- before_callbacks = [],
2351
- after_callbacks = []
2432
+ validate=True,
2433
+ verify=True,
2434
+ is_new=None,
2435
+ increment_a=None,
2436
+ immutables_a=None,
2437
+ pre_validate=True,
2438
+ pre_save=True,
2439
+ pre_create=True,
2440
+ pre_update=True,
2441
+ post_validate=True,
2442
+ post_save=True,
2443
+ post_create=True,
2444
+ post_update=True,
2445
+ before_callbacks=[],
2446
+ after_callbacks=[],
2352
2447
  ):
2353
2448
  # ensures that the current instance is associated with
2354
2449
  # a concrete model, ready to be persisted in database
2355
- if verify: self.assert_is_concrete()
2450
+ if verify:
2451
+ self.assert_is_concrete()
2356
2452
 
2357
2453
  # checks if the instance to be saved is a new instance
2358
2454
  # or if this is an update operation and then determines
2359
2455
  # series of default values taking that into account
2360
- if is_new == None: is_new = self.is_new()
2361
- if increment_a == None: increment_a = is_new
2362
- if immutables_a == None: immutables_a = not is_new
2456
+ if is_new == None:
2457
+ is_new = self.is_new()
2458
+ if increment_a == None:
2459
+ increment_a = is_new
2460
+ if immutables_a == None:
2461
+ immutables_a = not is_new
2363
2462
 
2364
2463
  # runs the validation process in the current model, this
2365
2464
  # should ensure that the model is ready to be saved in the
2366
2465
  # data source, without corruption of it, only run this process
2367
2466
  # in case the validate flag is correctly set
2368
2467
  validate and self._validate(
2369
- pre_validate = pre_validate,
2370
- post_validate = post_validate
2468
+ pre_validate=pre_validate, post_validate=post_validate
2371
2469
  )
2372
2470
 
2373
2471
  # calls the complete set of event handlers for the current
2374
2472
  # save operation, this should trigger changes in the model
2375
- if pre_save: self.pre_save()
2376
- if pre_create and is_new: self.pre_create()
2377
- if pre_update and not is_new: self.pre_update()
2473
+ if pre_save:
2474
+ self.pre_save()
2475
+ if pre_create and is_new:
2476
+ self.pre_create()
2477
+ if pre_update and not is_new:
2478
+ self.pre_update()
2378
2479
 
2379
2480
  # filters the values that are present in the current model
2380
2481
  # so that only the valid ones are stored in, invalid values
@@ -2384,37 +2485,42 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2384
2485
  # any relation is loaded the reference value is returned instead
2385
2486
  # of the loaded relation values (required for persistence)
2386
2487
  model = self._filter(
2387
- increment_a = increment_a,
2388
- immutables_a = immutables_a,
2389
- normalize = True
2488
+ increment_a=increment_a, immutables_a=immutables_a, normalize=True
2390
2489
  )
2391
2490
 
2392
2491
  # in case the current model is not new must create a new
2393
2492
  # model instance and remove the main identifier from it
2394
- if not is_new: _model = copy.copy(model); del _model["_id"]
2493
+ if not is_new:
2494
+ _model = copy.copy(model)
2495
+ del _model["_id"]
2395
2496
 
2396
2497
  # calls the complete set of callbacks that should be called
2397
2498
  # before the concrete data store save operation
2398
- for callback in before_callbacks: callback(self, model)
2499
+ for callback in before_callbacks:
2500
+ callback(self, model)
2399
2501
 
2400
2502
  # retrieves the reference to the store object to be used and
2401
2503
  # uses it to store the current model data
2402
2504
  store = self._get_store()
2403
2505
  if is_new:
2404
2506
  store.insert(model)
2405
- self.apply(model, safe_a = False)
2507
+ self.apply(model, safe_a=False)
2406
2508
  else:
2407
- store.update({"_id" : model["_id"]}, {"$set" : _model})
2509
+ store.update({"_id": model["_id"]}, {"$set": _model})
2408
2510
 
2409
2511
  # calls the complete set of callbacks that should be called
2410
2512
  # after the concrete data store save operation
2411
- for callback in after_callbacks: callback(self, model)
2513
+ for callback in after_callbacks:
2514
+ callback(self, model)
2412
2515
 
2413
2516
  # calls the post save event handlers in order to be able to
2414
2517
  # execute appropriate post operations
2415
- if post_save: self.post_save()
2416
- if post_create and is_new: self.post_create()
2417
- if post_update and not is_new: self.post_update()
2518
+ if post_save:
2519
+ self.post_save()
2520
+ if post_create and is_new:
2521
+ self.post_create()
2522
+ if post_update and not is_new:
2523
+ self.post_update()
2418
2524
 
2419
2525
  # returns the instance that has just been used for the save
2420
2526
  # operation, this may be used for chaining operations
@@ -2422,28 +2528,31 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2422
2528
 
2423
2529
  def delete(
2424
2530
  self,
2425
- verify = True,
2426
- pre_delete = True,
2427
- post_delete = True,
2428
- before_callbacks = [],
2429
- after_callbacks = []
2531
+ verify=True,
2532
+ pre_delete=True,
2533
+ post_delete=True,
2534
+ before_callbacks=[],
2535
+ after_callbacks=[],
2430
2536
  ):
2431
2537
  # ensures that the current instance is associated with
2432
2538
  # a concrete model, ready to be persisted in database
2433
- if verify: self.assert_is_concrete()
2539
+ if verify:
2540
+ self.assert_is_concrete()
2434
2541
 
2435
2542
  # calls the complete set of event handlers for the current
2436
2543
  # delete operation, this should trigger changes in the model
2437
- if pre_delete: self.pre_delete()
2544
+ if pre_delete:
2545
+ self.pre_delete()
2438
2546
 
2439
2547
  # calls the complete set of callbacks that should be called
2440
2548
  # before the concrete data store delete operation
2441
- for callback in before_callbacks: callback(self)
2549
+ for callback in before_callbacks:
2550
+ callback(self)
2442
2551
 
2443
2552
  # retrieves the reference to the store object to be able to
2444
2553
  # execute the removal command for the current model
2445
2554
  store = self._get_store()
2446
- store.remove({"_id" : self._id})
2555
+ store.remove({"_id": self._id})
2447
2556
 
2448
2557
  # calls the underlying delete handler that may be used to extend
2449
2558
  # the default delete functionality
@@ -2451,13 +2560,15 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2451
2560
 
2452
2561
  # calls the complete set of callbacks that should be called
2453
2562
  # after the concrete data store delete operation
2454
- for callback in after_callbacks: callback(self)
2563
+ for callback in after_callbacks:
2564
+ callback(self)
2455
2565
 
2456
2566
  # calls the complete set of event handlers for the current
2457
2567
  # delete operation, this should trigger changes in the model
2458
- if post_delete: self.post_delete()
2568
+ if post_delete:
2569
+ self.post_delete()
2459
2570
 
2460
- def approve(self, model = None, type = None):
2571
+ def approve(self, model=None, type=None):
2461
2572
  # retrieves the class associated with the instance
2462
2573
  # that is going to be sent for approval
2463
2574
  cls = self.__class__
@@ -2469,71 +2580,55 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2469
2580
  # retrieves the proper (target) method for validation
2470
2581
  # and then runs the inner validate method for it
2471
2582
  method = getattr(cls, "validate" + suffix)
2472
- self._validate(model = model, method = method)
2583
+ self._validate(model=model, method=method)
2473
2584
 
2474
2585
  # returns the instance that has just been used for the approve
2475
2586
  # operation, this may be used for chaining operations
2476
2587
  return self
2477
2588
 
2478
- def advance(self, name, delta = 1):
2589
+ def advance(self, name, delta=1):
2479
2590
  store = self._get_store()
2480
2591
  value = store.find_and_modify(
2481
- {
2482
- "_id" : self._id
2483
- },
2484
- {
2485
- "$inc" : {
2486
- name : delta
2487
- }
2488
- },
2489
- new = True
2592
+ {"_id": self._id}, {"$inc": {name: delta}}, new=True
2490
2593
  )
2491
- value = value or store.find_one({
2492
- "_id" : self._id
2493
- })
2594
+ value = value or store.find_one({"_id": self._id})
2494
2595
  _value = value[name]
2495
2596
  setattr(self, name, _value)
2496
2597
  return _value
2497
2598
 
2498
2599
  def reload(self, *args, **kwargs):
2499
2600
  is_new = self.is_new()
2500
- if is_new: raise exceptions.OperationalError(
2501
- message = "Can't reload a new model entity",
2502
- code = 412
2503
- )
2601
+ if is_new:
2602
+ raise exceptions.OperationalError(
2603
+ message="Can't reload a new model entity", code=412
2604
+ )
2504
2605
  cls = self.__class__
2505
- return cls.get(_id = self._id, *args, **kwargs)
2606
+ return cls.get(_id=self._id, *args, **kwargs)
2506
2607
 
2507
2608
  def exists(self):
2508
2609
  is_new = self.is_new()
2509
- if is_new: return False
2510
- entity = self.get(_id = self._id, raise_e = False)
2610
+ if is_new:
2611
+ return False
2612
+ entity = self.get(_id=self._id, raise_e=False)
2511
2613
  return True if entity else False
2512
2614
 
2513
- def map(
2514
- self,
2515
- increment_a = False,
2516
- resolve = False,
2517
- all = False,
2518
- evaluator = "map_v"
2519
- ):
2615
+ def map(self, increment_a=False, resolve=False, all=False, evaluator="map_v"):
2520
2616
  model = self._filter(
2521
- increment_a = increment_a,
2522
- resolve = resolve,
2523
- all = all,
2524
- evaluator = evaluator
2617
+ increment_a=increment_a, resolve=resolve, all=all, evaluator=evaluator
2525
2618
  )
2526
2619
  return model
2527
2620
 
2528
- def dumps(self, encode = True):
2621
+ def dumps(self, encode=True):
2529
2622
  cls = self.__class__
2530
2623
  encoder = cls._encoder() if encode else None
2531
- return json.dumps(self.model, cls = encoder)
2624
+ return json.dumps(self.model, cls=encoder)
2532
2625
 
2533
2626
  def unwrap(self, **kwargs):
2534
2627
  default = kwargs.get("default", False)
2535
- if default: return self.map()
2536
- else: return dict()
2628
+ if default:
2629
+ return self.map()
2630
+ else:
2631
+ return dict()
2537
2632
 
2538
2633
  def pre_validate(self):
2539
2634
  self.trigger("pre_validate")
@@ -2580,16 +2675,11 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2580
2675
  def _delete(self):
2581
2676
  pass
2582
2677
 
2583
- def _validate(
2584
- self,
2585
- model = None,
2586
- method = None,
2587
- pre_validate = True,
2588
- post_validate = True
2589
- ):
2678
+ def _validate(self, model=None, method=None, pre_validate=True, post_validate=True):
2590
2679
  # calls the event handler for the validation process this
2591
2680
  # should setup the operations for a correct validation
2592
- if pre_validate: self.pre_validate()
2681
+ if pre_validate:
2682
+ self.pre_validate()
2593
2683
 
2594
2684
  # starts the model reference with the current model in
2595
2685
  # case none is defined
@@ -2602,17 +2692,16 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2602
2692
  # checks if the current model is new (create operation)
2603
2693
  # and sets the proper validation methods retrieval method
2604
2694
  is_new = self.is_new()
2605
- if is_new: method = method or cls.validate_new
2606
- else: method = method or cls.validate
2695
+ if is_new:
2696
+ method = method or cls.validate_new
2697
+ else:
2698
+ method = method or cls.validate
2607
2699
 
2608
2700
  # runs the validation process on the various arguments
2609
2701
  # provided to the account and in case an error is returned
2610
2702
  # raises a validation error to the upper layers
2611
2703
  errors, object = validation.validate(
2612
- method,
2613
- object = model,
2614
- ctx = self,
2615
- build = False
2704
+ method, object=model, ctx=self, build=False
2616
2705
  )
2617
2706
 
2618
2707
  # iterates over the complete set of extra validate method
@@ -2622,10 +2711,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2622
2711
  # from an end-user point of view (as expected)
2623
2712
  for extra in self._extras:
2624
2713
  _errors, _object = validation.validate(
2625
- extra,
2626
- object = model,
2627
- ctx = self,
2628
- build = False
2714
+ extra, object=model, ctx=self, build=False
2629
2715
  )
2630
2716
  for key, value in _errors.items():
2631
2717
  errors_l = errors.get(key, [])
@@ -2640,20 +2726,22 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2640
2726
  # in case the errors map is not empty or invalid there are
2641
2727
  # errors and they should be encapsulated around a validation
2642
2728
  # error and raises to the top layer for handling
2643
- if errors: raise exceptions.ValidationError(errors, self)
2729
+ if errors:
2730
+ raise exceptions.ValidationError(errors, self)
2644
2731
 
2645
2732
  # calls the event handler for the validation process this
2646
2733
  # should finish the operations from a correct validation
2647
- if post_validate: self.post_validate()
2734
+ if post_validate:
2735
+ self.post_validate()
2648
2736
 
2649
2737
  def _filter(
2650
2738
  self,
2651
- increment_a = True,
2652
- immutables_a = False,
2653
- normalize = False,
2654
- resolve = False,
2655
- all = False,
2656
- evaluator = "json_v"
2739
+ increment_a=True,
2740
+ immutables_a=False,
2741
+ normalize=False,
2742
+ resolve=False,
2743
+ all=False,
2744
+ evaluator="json_v",
2657
2745
  ):
2658
2746
  # creates the model that will hold the "filtered" model
2659
2747
  # with all the items that conform with the class specification
@@ -2681,7 +2769,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2681
2769
  # fields so that a new value is set on the model, note that if
2682
2770
  # the increment apply is unset the increment operation is ignored
2683
2771
  for name in increments:
2684
- if not increment_a: continue
2772
+ if not increment_a:
2773
+ continue
2685
2774
  if name in self.model:
2686
2775
  model[name] = cls._ensure_min(name, self.model[name])
2687
2776
  else:
@@ -2690,10 +2779,13 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2690
2779
  # iterates over all the model items to filter the ones
2691
2780
  # that are not valid for the current class context
2692
2781
  for name, value in legacy.eager(self.model.items()):
2693
- if not name in definition: continue
2694
- if increment_a and name in increments: continue
2695
- if immutables_a and name in immutables: continue
2696
- value = self._evaluate(name, value, evaluator = evaluator)
2782
+ if not name in definition:
2783
+ continue
2784
+ if increment_a and name in increments:
2785
+ continue
2786
+ if immutables_a and name in immutables:
2787
+ continue
2788
+ value = self._evaluate(name, value, evaluator=evaluator)
2697
2789
  model[name] = value
2698
2790
 
2699
2791
  # in case the normalize flag is set must iterate over all
@@ -2702,8 +2794,10 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2702
2794
  # the normal value that would prevent normalization
2703
2795
  if normalize:
2704
2796
  for name, value in legacy.eager(self.model.items()):
2705
- if not name in definition: continue
2706
- if not hasattr(value, "ref_v"): continue
2797
+ if not name in definition:
2798
+ continue
2799
+ if not hasattr(value, "ref_v"):
2800
+ continue
2707
2801
  model[name] = value.ref_v()
2708
2802
 
2709
2803
  # in case the resolution flag is set, it means that a recursive
@@ -2713,7 +2807,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2713
2807
  # may imply access to the base data source
2714
2808
  if resolve:
2715
2809
  for name, value in legacy.eager(self.model.items()):
2716
- if not name in definition: continue
2810
+ if not name in definition:
2811
+ continue
2717
2812
  model[name] = cls._resolve(name, value)
2718
2813
 
2719
2814
  # in case the all flag is set the extra fields (not present
@@ -2722,14 +2817,15 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2722
2817
  # present in the base map of the current instance
2723
2818
  if all:
2724
2819
  for name, value in legacy.eager(self.model.items()):
2725
- if name in model: continue
2820
+ if name in model:
2821
+ continue
2726
2822
  model[name] = value
2727
2823
 
2728
2824
  # returns the model containing the "filtered" items resulting
2729
2825
  # from the validation of the items against the model class
2730
2826
  return model
2731
2827
 
2732
- def _evaluate(self, name, value, evaluator = "json_v"):
2828
+ def _evaluate(self, name, value, evaluator="json_v"):
2733
2829
  # verifies if the current value is an iterable one in case
2734
2830
  # it is runs the evaluate method for each of the values to
2735
2831
  # try to resolve them into the proper representation, note
@@ -2737,12 +2833,13 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2737
2833
  # objects that implement the evaluator method are not considered
2738
2834
  # to be iterables and normal operation applies
2739
2835
  is_iterable = hasattr(value, "__iter__")
2740
- is_iterable = is_iterable and not isinstance(value, ITERABLES) and\
2741
- (not hasattr(value, evaluator) or not evaluator)
2742
- if is_iterable: return [
2743
- self._evaluate(name, value, evaluator = evaluator) for\
2744
- value in value
2745
- ]
2836
+ is_iterable = (
2837
+ is_iterable
2838
+ and not isinstance(value, ITERABLES)
2839
+ and (not hasattr(value, evaluator) or not evaluator)
2840
+ )
2841
+ if is_iterable:
2842
+ return [self._evaluate(name, value, evaluator=evaluator) for value in value]
2746
2843
 
2747
2844
  # verifies the current value's class is sub class of the model
2748
2845
  # class and in case it's extracts the relation name from the
@@ -2757,8 +2854,12 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2757
2854
  # iterates over all the values and retrieves the map value for
2758
2855
  # each of them in case the value contains a map value retrieval
2759
2856
  # method otherwise uses the normal value returning it to the caller
2760
- method = getattr(value, evaluator) if evaluator and hasattr(value, evaluator) else None
2761
- value = method(resolve = False) if method else value
2857
+ method = (
2858
+ getattr(value, evaluator)
2859
+ if evaluator and hasattr(value, evaluator)
2860
+ else None
2861
+ )
2862
+ value = method(resolve=False) if method else value
2762
2863
  return value
2763
2864
 
2764
2865
  def _res_entity(self, name, *args, **kwargs):
@@ -2782,7 +2883,8 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2782
2883
 
2783
2884
  # in case the provided name is a simple one this is a direct attribute
2784
2885
  # of the current entity and so the expected values are returned
2785
- if not "." in name: return self, name
2886
+ if not "." in name:
2887
+ return self, name
2786
2888
 
2787
2889
  # sets the initial entity value for iteration as the current instance
2788
2890
  # (root node) and then splits the name around its components
@@ -2798,6 +2900,7 @@ class Model(legacy.with_meta(meta.Ordered, observer.Observable, *EXTRA_CLS)):
2798
2900
  # final name of the attribute on the leaf node
2799
2901
  return entity, name_s[-1]
2800
2902
 
2903
+
2801
2904
  class LocalModel(Model):
2802
2905
  """
2803
2906
  Concrete model aimed at cases where data source based
@@ -2812,6 +2915,7 @@ class LocalModel(Model):
2812
2915
  def is_attached(cls):
2813
2916
  return False
2814
2917
 
2918
+
2815
2919
  class Field(dict):
2816
2920
  """
2817
2921
  Top level field class that should be used for the
@@ -2832,9 +2936,11 @@ class Field(dict):
2832
2936
  Field.creation_counter += 1
2833
2937
 
2834
2938
  def __getattr__(self, name):
2835
- if name in self: return self[name]
2939
+ if name in self:
2940
+ return self[name]
2836
2941
  raise AttributeError("'%s' not found" % name)
2837
2942
 
2943
+
2838
2944
  class Action(dict):
2839
2945
  """
2840
2946
  The abstract class that defines an action to be performed
@@ -2846,10 +2952,11 @@ class Action(dict):
2846
2952
  """
2847
2953
 
2848
2954
  def __getattr__(self, name):
2849
- if name in self: return self[name]
2955
+ if name in self:
2956
+ return self[name]
2850
2957
  raise AttributeError("'%s' not found" % name)
2851
2958
 
2852
- def cast(self, values, keyword = False):
2959
+ def cast(self, values, keyword=False):
2853
2960
  """
2854
2961
  Runs the "casting" operation for a series of provided
2855
2962
  values, the order sequence of the provided values is
@@ -2882,15 +2989,20 @@ class Action(dict):
2882
2989
  cast = type
2883
2990
  is_default = value in (None, "")
2884
2991
  cast = BUILDERS.get(cast, cast)
2885
- if cast and not is_default: value = cast(value)
2886
- if is_default: value = type_d(type, value)
2887
- if keyword: casted[name] = value
2888
- else: casted.append(value)
2992
+ if cast and not is_default:
2993
+ value = cast(value)
2994
+ if is_default:
2995
+ value = type_d(type, value)
2996
+ if keyword:
2997
+ casted[name] = value
2998
+ else:
2999
+ casted.append(value)
2889
3000
 
2890
3001
  # returns the final list/map of casted values to the caller method
2891
3002
  # so that it may be used safely in the context
2892
3003
  return casted
2893
3004
 
3005
+
2894
3006
  class Link(Action):
2895
3007
  """
2896
3008
  Internal link class used to encapsulate some of the
@@ -2900,6 +3012,7 @@ class Link(Action):
2900
3012
 
2901
3013
  pass
2902
3014
 
3015
+
2903
3016
  class Operation(Action):
2904
3017
  """
2905
3018
  Logical structure representing an operation, should
@@ -2909,6 +3022,7 @@ class Operation(Action):
2909
3022
 
2910
3023
  pass
2911
3024
 
3025
+
2912
3026
  class View(Action):
2913
3027
  """
2914
3028
  Definition associated with a model that represents
@@ -2918,13 +3032,8 @@ class View(Action):
2918
3032
 
2919
3033
  pass
2920
3034
 
2921
- def link(
2922
- name = None,
2923
- description = None,
2924
- parameters = (),
2925
- context = False,
2926
- devel = False
2927
- ):
3035
+
3036
+ def link(name=None, description=None, parameters=(), context=False, devel=False):
2928
3037
  """
2929
3038
  Decorator function to be used to "annotate" the provided
2930
3039
  function as an link (string) that is able to change the user
@@ -2955,25 +3064,26 @@ def link(
2955
3064
 
2956
3065
  def decorator(function, *args, **kwargs):
2957
3066
  function._link = Link(
2958
- method = function.__name__,
2959
- name = name or function.__name__,
2960
- description = description,
2961
- parameters = parameters,
2962
- context = context,
2963
- devel = devel
3067
+ method=function.__name__,
3068
+ name=name or function.__name__,
3069
+ description=description,
3070
+ parameters=parameters,
3071
+ context=context,
3072
+ devel=devel,
2964
3073
  )
2965
3074
  return function
2966
3075
 
2967
3076
  return decorator
2968
3077
 
3078
+
2969
3079
  def operation(
2970
- name = None,
2971
- description = None,
2972
- parameters = (),
2973
- kwargs = None,
2974
- factory = False,
2975
- level = 1,
2976
- devel = False
3080
+ name=None,
3081
+ description=None,
3082
+ parameters=(),
3083
+ kwargs=None,
3084
+ factory=False,
3085
+ level=1,
3086
+ devel=False,
2977
3087
  ):
2978
3088
  """
2979
3089
  Decorator function to be used to "annotate" the provided
@@ -3015,26 +3125,22 @@ def operation(
3015
3125
 
3016
3126
  def decorator(function, *args, **kwargs):
3017
3127
  function._operation = Operation(
3018
- method = function.__name__,
3019
- name = name or function.__name__,
3020
- description = description,
3021
- parameters = parameters,
3022
- kwargs = _kwargs,
3023
- factory = factory,
3024
- level = level,
3025
- devel = devel
3128
+ method=function.__name__,
3129
+ name=name or function.__name__,
3130
+ description=description,
3131
+ parameters=parameters,
3132
+ kwargs=_kwargs,
3133
+ factory=factory,
3134
+ level=level,
3135
+ devel=devel,
3026
3136
  )
3027
3137
 
3028
3138
  return function
3029
3139
 
3030
3140
  return decorator
3031
3141
 
3032
- def view(
3033
- name = None,
3034
- description = None,
3035
- parameters = (),
3036
- devel = False
3037
- ):
3142
+
3143
+ def view(name=None, description=None, parameters=(), devel=False):
3038
3144
  """
3039
3145
  Decorator function to be used to "annotate" the provided
3040
3146
  function as an view that is able to return a set of configurations
@@ -3062,18 +3168,19 @@ def view(
3062
3168
 
3063
3169
  def decorator(function, *args, **kwargs):
3064
3170
  function._view = View(
3065
- method = function.__name__,
3066
- name = name or function.__name__,
3067
- description = description,
3068
- parameters = parameters,
3069
- devel = devel
3171
+ method=function.__name__,
3172
+ name=name or function.__name__,
3173
+ description=description,
3174
+ parameters=parameters,
3175
+ devel=devel,
3070
3176
  )
3071
3177
 
3072
3178
  return function
3073
3179
 
3074
3180
  return decorator
3075
3181
 
3076
- def type_d(type, default = None):
3182
+
3183
+ def type_d(type, default=None):
3077
3184
  """
3078
3185
  Retrieves the default (initial) value for the a certain
3079
3186
  provided data type falling back to the provided default
@@ -3097,11 +3204,14 @@ def type_d(type, default = None):
3097
3204
  to the best possible strategy.
3098
3205
  """
3099
3206
 
3100
- if not type in TYPE_DEFAULTS: return default
3207
+ if not type in TYPE_DEFAULTS:
3208
+ return default
3101
3209
  default = TYPE_DEFAULTS[type]
3102
- if not hasattr(default, "__call__"): return default
3210
+ if not hasattr(default, "__call__"):
3211
+ return default
3103
3212
  return default()
3104
3213
 
3214
+
3105
3215
  def is_unset(value):
3106
3216
  """
3107
3217
  Verifies if the provided value is unset trying the multiple
@@ -3118,9 +3228,11 @@ def is_unset(value):
3118
3228
  underlying promises of the data type of the provided value.
3119
3229
  """
3120
3230
 
3121
- if value == None: return True
3122
- if isinstance(value, typesf.Reference) and\
3123
- not value.is_resolvable(): return True
3231
+ if value == None:
3232
+ return True
3233
+ if isinstance(value, typesf.Reference) and not value.is_resolvable():
3234
+ return True
3124
3235
  return False
3125
3236
 
3237
+
3126
3238
  field = Field