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/execution.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"
@@ -61,6 +52,7 @@ background_t = None
61
52
  """ The background execution task to be started by
62
53
  the appier execution system (global value) """
63
54
 
55
+
64
56
  class ExecutionThread(threading.Thread):
65
57
  """
66
58
  The thread to be used in the execution of "random"
@@ -88,7 +80,7 @@ class ExecutionThread(threading.Thread):
88
80
  Constructor of the class.
89
81
  """
90
82
 
91
- threading.Thread.__init__(self, name = "Execution")
83
+ threading.Thread.__init__(self, name="Execution")
92
84
 
93
85
  self.daemon = True
94
86
  self.work_list = []
@@ -118,7 +110,8 @@ class ExecutionThread(threading.Thread):
118
110
  while True:
119
111
  # in case there is no work pending to be
120
112
  # executed must exist immediately
121
- if not self.work_list: break
113
+ if not self.work_list:
114
+ break
122
115
 
123
116
  # retrieves the current work tuple to
124
117
  # be used and executes it in case the
@@ -144,18 +137,20 @@ class ExecutionThread(threading.Thread):
144
137
  # executes the "callable" and logs the error in case the
145
138
  # execution fails (must be done to log the error) then
146
139
  # sets the error flag with the exception variable
147
- try: callable(*args, **kwargs)
140
+ try:
141
+ callable(*args, **kwargs)
148
142
  except Exception as exception:
149
143
  error = exception
150
144
  lines = traceback.format_exc().splitlines()
151
145
  logger = common.base().get_logger()
152
146
  logger.warning(str(exception))
153
- for line in lines: logger.info(line)
147
+ for line in lines:
148
+ logger.info(line)
154
149
 
155
150
  # calls the callback method with the currently set error
156
151
  # in order to notify the runtime about the problem, only
157
152
  # calls the callback in case such method is defined
158
- callback and callback(error = error)
153
+ callback and callback(error=error)
159
154
 
160
155
  # sleeps for a while so that the process may
161
156
  # released for different tasks
@@ -164,20 +159,25 @@ class ExecutionThread(threading.Thread):
164
159
  def stop(self):
165
160
  self.run_flag = False
166
161
 
167
- def insert_work(self, callable, args = [], kwargs = {}, target_time = None, callback = None):
162
+ def insert_work(
163
+ self, callable, args=[], kwargs={}, target_time=None, callback=None
164
+ ):
168
165
  target_time = target_time or time.time()
169
166
  work = (target_time, callable, callback, args, kwargs)
170
167
  self.work_lock.acquire()
171
- try: heapq.heappush(self.work_list, work)
172
- finally: self.work_lock.release()
168
+ try:
169
+ heapq.heappush(self.work_list, work)
170
+ finally:
171
+ self.work_lock.release()
173
172
 
174
- def background(timeout = None):
175
173
 
174
+ def background(timeout=None):
176
175
  def decorator(function):
177
176
  _timeout = timeout or 0.0
178
177
 
179
- def schedule(error = None, force = False):
180
- if timeout == None and not force: return
178
+ def schedule(error=None, force=False):
179
+ if timeout == None and not force:
180
+ return
181
181
  target = time.time() + _timeout
182
182
  insert_work(function, target, schedule)
183
183
 
@@ -187,18 +187,20 @@ def background(timeout = None):
187
187
  # immediately (nothing to be done, duplicate)
188
188
  fname = function.__name__
189
189
  exists = fname in BACKGROUND
190
- if exists: return function
190
+ if exists:
191
+ return function
191
192
 
192
193
  # runs the scheduling operation on the task and
193
194
  # then adds the function name to the list of already
194
195
  # registered names
195
- schedule(force = True)
196
+ schedule(force=True)
196
197
  BACKGROUND.append(fname)
197
198
  return function
198
199
 
199
200
  return decorator
200
201
 
201
- def insert_work(callable, args = [], kwargs = {}, target_time = None, callback = None):
202
+
203
+ def insert_work(callable, args=[], kwargs={}, target_time=None, callback=None):
202
204
  """
203
205
  Runs the provided callable (function, method, etc) in a separated
204
206
  thread context under submission of a queue system.
@@ -231,114 +233,116 @@ def insert_work(callable, args = [], kwargs = {}, target_time = None, callback =
231
233
  """
232
234
 
233
235
  background_t.insert_work(
234
- callable,
235
- args = args,
236
- kwargs = kwargs,
237
- target_time = target_time,
238
- callback = callback
236
+ callable, args=args, kwargs=kwargs, target_time=target_time, callback=callback
239
237
  )
240
238
 
239
+
241
240
  def interval_work(
242
- callable,
243
- args = [],
244
- kwargs = {},
245
- callback = None,
246
- initial = None,
247
- interval = 60,
248
- eval = None
241
+ callable, args=[], kwargs={}, callback=None, initial=None, interval=60, eval=None
249
242
  ):
250
243
  initial = initial or (eval and eval()) or time.time()
251
244
  composed = build_composed(callable, initial, interval, eval, callback)
252
245
  insert_work(
253
- composed,
254
- args = args,
255
- kwargs = kwargs,
256
- target_time = initial,
257
- callback = callback
246
+ composed, args=args, kwargs=kwargs, target_time=initial, callback=callback
258
247
  )
259
248
  return initial
260
249
 
261
- def seconds_work(callable, offset = 0, *args, **kwargs):
250
+
251
+ def seconds_work(callable, offset=0, *args, **kwargs):
262
252
  eval = lambda: seconds_eval(offset)
263
- return interval_work(callable, eval = eval, *args, **kwargs)
253
+ return interval_work(callable, eval=eval, *args, **kwargs)
264
254
 
265
- def minutes_work(callable, offset = 0, *args, **kwargs):
255
+
256
+ def minutes_work(callable, offset=0, *args, **kwargs):
266
257
  eval = lambda: minutes_eval(offset)
267
- return interval_work(callable, eval = eval, *args, **kwargs)
258
+ return interval_work(callable, eval=eval, *args, **kwargs)
259
+
268
260
 
269
- def hourly_work(callable, offset = 0, *args, **kwargs):
261
+ def hourly_work(callable, offset=0, *args, **kwargs):
270
262
  eval = lambda: hourly_eval(offset)
271
- return interval_work(callable, eval = eval, *args, **kwargs)
263
+ return interval_work(callable, eval=eval, *args, **kwargs)
264
+
272
265
 
273
- def daily_work(callable, offset = 0, *args, **kwargs):
266
+ def daily_work(callable, offset=0, *args, **kwargs):
274
267
  eval = lambda: daily_eval(offset)
275
- return interval_work(callable, eval = eval, *args, **kwargs)
268
+ return interval_work(callable, eval=eval, *args, **kwargs)
276
269
 
277
- def weekly_work(callable, weekday = 4, offset = 0, *args, **kwargs):
270
+
271
+ def weekly_work(callable, weekday=4, offset=0, *args, **kwargs):
278
272
  eval = lambda: weekly_eval(weekday, offset)
279
- return interval_work(callable, eval = eval, *args, **kwargs)
273
+ return interval_work(callable, eval=eval, *args, **kwargs)
274
+
280
275
 
281
- def monthly_work(callable, monthday = 1, offset = 0, *args, **kwargs):
276
+ def monthly_work(callable, monthday=1, offset=0, *args, **kwargs):
282
277
  eval = lambda: monthly_eval(monthday, offset)
283
- return interval_work(callable, eval = eval, *args, **kwargs)
278
+ return interval_work(callable, eval=eval, *args, **kwargs)
284
279
 
285
- def seconds_eval(offset, now = None):
280
+
281
+ def seconds_eval(offset, now=None):
286
282
  now = now or datetime.datetime.utcnow()
287
- next = now + datetime.timedelta(seconds = offset)
283
+ next = now + datetime.timedelta(seconds=offset)
288
284
  next_tuple = next.utctimetuple()
289
285
  return calendar.timegm(next_tuple)
290
286
 
291
- def minutes_eval(offset, now = None):
287
+
288
+ def minutes_eval(offset, now=None):
292
289
  now = now or datetime.datetime.utcnow()
293
290
  current = datetime.datetime(
294
- year = now.year,
295
- month = now.month,
296
- day = now.day,
297
- hour = now.hour,
298
- minute = now.minute
291
+ year=now.year, month=now.month, day=now.day, hour=now.hour, minute=now.minute
299
292
  )
300
- next = current + datetime.timedelta(minutes = 1, seconds = offset)
293
+ next = current + datetime.timedelta(minutes=1, seconds=offset)
301
294
  next_tuple = next.utctimetuple()
302
295
  return calendar.timegm(next_tuple)
303
296
 
304
- def hourly_eval(offset, now = None):
297
+
298
+ def hourly_eval(offset, now=None):
305
299
  now = now or datetime.datetime.utcnow()
306
- current = datetime.datetime(year = now.year, month = now.month, day = now.day, hour = now.hour)
307
- next = current + datetime.timedelta(hours = 1, seconds = offset)
300
+ current = datetime.datetime(
301
+ year=now.year, month=now.month, day=now.day, hour=now.hour
302
+ )
303
+ next = current + datetime.timedelta(hours=1, seconds=offset)
308
304
  next_tuple = next.utctimetuple()
309
305
  return calendar.timegm(next_tuple)
310
306
 
311
- def daily_eval(offset, now = None):
307
+
308
+ def daily_eval(offset, now=None):
312
309
  now = now or datetime.datetime.utcnow()
313
- today = datetime.datetime(year = now.year, month = now.month, day = now.day)
314
- tomorrow = today + datetime.timedelta(days = 1, seconds = offset)
310
+ today = datetime.datetime(year=now.year, month=now.month, day=now.day)
311
+ tomorrow = today + datetime.timedelta(days=1, seconds=offset)
315
312
  tomorrow_tuple = tomorrow.utctimetuple()
316
313
  return calendar.timegm(tomorrow_tuple)
317
314
 
318
- def weekly_eval(weekday, offset, now = None):
315
+
316
+ def weekly_eval(weekday, offset, now=None):
319
317
  now = now or datetime.datetime.utcnow()
320
- today = datetime.datetime(year = now.year, month = now.month, day = now.day)
318
+ today = datetime.datetime(year=now.year, month=now.month, day=now.day)
321
319
  distance = (weekday - today.weekday()) % 7
322
- weekday = today + datetime.timedelta(days = distance, seconds = offset)
323
- if weekday < now: weekday += datetime.timedelta(days = 7)
320
+ weekday = today + datetime.timedelta(days=distance, seconds=offset)
321
+ if weekday < now:
322
+ weekday += datetime.timedelta(days=7)
324
323
  weekday_tuple = weekday.utctimetuple()
325
324
  return calendar.timegm(weekday_tuple)
326
325
 
327
- def monthly_eval(monthday, offset, now = None):
326
+
327
+ def monthly_eval(monthday, offset, now=None):
328
328
  now = now or datetime.datetime.utcnow()
329
- next_year, next_month = (now.year + 1, 1) if now.month == 12 else (now.year, now.month + 1)
330
- if now.day > monthday: month, year = (next_month, next_year)
331
- else: month, year = (now.month, now.year)
332
- monthday = datetime.datetime(year = year, month = month, day = monthday)
333
- monthday = monthday + datetime.timedelta(seconds = offset)
329
+ next_year, next_month = (
330
+ (now.year + 1, 1) if now.month == 12 else (now.year, now.month + 1)
331
+ )
332
+ if now.day > monthday:
333
+ month, year = (next_month, next_year)
334
+ else:
335
+ month, year = (now.month, now.year)
336
+ monthday = datetime.datetime(year=year, month=month, day=monthday)
337
+ monthday = monthday + datetime.timedelta(seconds=offset)
334
338
  if monthday < now:
335
- monthday = datetime.datetime(year = next_year, month = next_month, day = monthday.day)
336
- monthday += datetime.timedelta(seconds = offset)
339
+ monthday = datetime.datetime(year=next_year, month=next_month, day=monthday.day)
340
+ monthday += datetime.timedelta(seconds=offset)
337
341
  monthday_tuple = monthday.utctimetuple()
338
342
  return calendar.timegm(monthday_tuple)
339
343
 
340
- def build_composed(callable, target_time, interval, eval, callback):
341
344
 
345
+ def build_composed(callable, target_time, interval, eval, callback):
342
346
  def composed(*args, **kwargs):
343
347
  try:
344
348
  # runs the initial callable, propagating the provided normal arguments
@@ -358,18 +362,20 @@ def build_composed(callable, target_time, interval, eval, callback):
358
362
  final = time.time()
359
363
  delta = final - target_time
360
364
  is_valid = delta < interval
361
- if is_valid: next_time = target_time + interval
362
- else: next_time = final + interval
365
+ if is_valid:
366
+ next_time = target_time + interval
367
+ else:
368
+ next_time = final + interval
363
369
 
364
370
  # builds a new callable (composed) method taking into account the state and
365
371
  # inserts the work unit again into the queue of processing
366
372
  composed = build_composed(callable, next_time, interval, eval, callback)
367
373
  insert_work(
368
374
  composed,
369
- args = args,
370
- kwargs = kwargs,
371
- target_time = next_time,
372
- callback = callback
375
+ args=args,
376
+ kwargs=kwargs,
377
+ target_time=next_time,
378
+ callback=callback,
373
379
  )
374
380
 
375
381
  # returns the current result from the original callable to the calling method,
appier/export.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"
@@ -66,18 +57,18 @@ basically adds new fields or updates existing fields in a previously
66
57
  existing document, this strategy does not remove extra fields existing
67
58
  in the previous document """
68
59
 
69
- class ExportManager(object):
70
60
 
61
+ class ExportManager(object):
71
62
  adapter = None
72
63
  single = None
73
64
  multiple = None
74
65
 
75
- def __init__(self, adapter, single = (), multiple = ()):
66
+ def __init__(self, adapter, single=(), multiple=()):
76
67
  self.adapter = adapter
77
68
  self.single = single
78
69
  self.multiple = multiple
79
70
 
80
- def import_data(self, file_path, policy = IGNORE):
71
+ def import_data(self, file_path, policy=IGNORE):
81
72
  temporary_path = tempfile.mkdtemp()
82
73
  base_path = temporary_path
83
74
  single_path = os.path.join(base_path, "settings")
@@ -88,18 +79,16 @@ class ExportManager(object):
88
79
  collection = self.adapter.collection(name)
89
80
  source_path = os.path.join(single_path, "%s.json" % name)
90
81
  file = open(source_path, "rb")
91
- try: data = file.read()
92
- finally: file.close()
93
- self._import_single(
94
- collection,
95
- data,
96
- key = key,
97
- policy = policy
98
- )
82
+ try:
83
+ data = file.read()
84
+ finally:
85
+ file.close()
86
+ self._import_single(collection, data, key=key, policy=policy)
99
87
 
100
88
  for name, key in self.multiple:
101
89
  source_directory = os.path.join(base_path, name)
102
- if not os.path.exists(source_directory): continue
90
+ if not os.path.exists(source_directory):
91
+ continue
103
92
 
104
93
  collection = self.adapter.collection(name)
105
94
  items = os.listdir(source_directory)
@@ -109,49 +98,52 @@ class ExportManager(object):
109
98
  value, _extension = os.path.splitext(item)
110
99
  source_path = os.path.join(source_directory, item)
111
100
  file = open(source_path, "rb")
112
- try: _data = file.read()
113
- finally: file.close()
101
+ try:
102
+ _data = file.read()
103
+ finally:
104
+ file.close()
114
105
 
115
106
  data.append((value, _data))
116
107
 
117
- self._import_multiple(
118
- collection,
119
- data,
120
- key = key,
121
- policy = policy
122
- )
108
+ self._import_multiple(collection, data, key=key, policy=policy)
123
109
 
124
110
  def export_data(self, file_path):
125
111
  encoder = self.adapter.encoder()
126
112
  temporary_path = tempfile.mkdtemp()
127
113
  base_path = temporary_path
128
114
  single_path = os.path.join(base_path, "settings")
129
- if not os.path.exists(single_path): os.makedirs(single_path)
115
+ if not os.path.exists(single_path):
116
+ os.makedirs(single_path)
130
117
 
131
118
  for name, key in self.single:
132
119
  collection = self.adapter.collection(name)
133
- data = self._export_single(collection, key = key, encoder = encoder)
120
+ data = self._export_single(collection, key=key, encoder=encoder)
134
121
  target_path = os.path.join(single_path, "%s.json" % name)
135
122
  file = open(target_path, "wb")
136
- try: file.write(data)
137
- finally: file.close()
123
+ try:
124
+ file.write(data)
125
+ finally:
126
+ file.close()
138
127
 
139
128
  for name, key in self.multiple:
140
129
  collection = self.adapter.collection(name)
141
- data = self._export_multiple(collection, key = key, encoder = encoder)
130
+ data = self._export_multiple(collection, key=key, encoder=encoder)
142
131
 
143
132
  target_directory = os.path.join(base_path, name)
144
- if not os.path.exists(target_directory): os.makedirs(target_directory)
133
+ if not os.path.exists(target_directory):
134
+ os.makedirs(target_directory)
145
135
 
146
136
  for value, _data in data:
147
137
  target_path = os.path.join(target_directory, "%s.json" % value)
148
138
  file = open(target_path, "wb")
149
- try: file.write(_data)
150
- finally: file.close()
139
+ try:
140
+ file.write(_data)
141
+ finally:
142
+ file.close()
151
143
 
152
144
  self._create_zip(file_path, temporary_path)
153
145
 
154
- def _import_single(self, collection, data, key, policy = IGNORE):
146
+ def _import_single(self, collection, data, key, policy=IGNORE):
155
147
  # loads the provided JSON data as a sequence of key value items
156
148
  # and then starts loading all the values into the data source
157
149
  data = data.decode("utf-8")
@@ -164,37 +156,41 @@ class ExportManager(object):
164
156
  # that in case the underlying identifiers does not exists a
165
157
  # new value is generated using the pre-defined strategy
166
158
  if "_id" in entity:
167
- try: entity["_id"] = self.adapter.object_id(entity["_id"])
168
- except Exception: entity["_id"] = entity["_id"]
169
- else: entity["_id"] = self.adapter.object_id()
159
+ try:
160
+ entity["_id"] = self.adapter.object_id(entity["_id"])
161
+ except Exception:
162
+ entity["_id"] = entity["_id"]
163
+ else:
164
+ entity["_id"] = self.adapter.object_id()
170
165
 
171
166
  # retrieves the key value for the current entity to
172
167
  # be inserted and then tries to retrieve an existing
173
168
  # entity for the same key, to avoid duplicated entry
174
169
  value = entity.get(key, None)
175
- if value: entity_e = collection.find_one({key : value})
176
- else: entity_e = None
170
+ if value:
171
+ entity_e = collection.find_one({key: value})
172
+ else:
173
+ entity_e = None
177
174
 
178
175
  # in case there's no existing entity for the same key
179
176
  # (normal situation) only need to insert the new entity
180
177
  # otherwise must apply the selected conflict policy for
181
178
  # the resolution of the data source conflict
182
- if not entity_e: collection.insert(entity)
183
- elif policy == IGNORE: continue
179
+ if not entity_e:
180
+ collection.insert(entity)
181
+ elif policy == IGNORE:
182
+ continue
184
183
  elif policy == OVERWRITE:
185
- collection.remove({key : value})
184
+ collection.remove({key: value})
186
185
  collection.insert(entity)
187
186
  elif policy == DUPLICATE:
188
187
  collection.insert(entity)
189
188
  elif policy == JOIN:
190
- if "_id" in entity: del entity["_id"]
191
- collection.update({
192
- "_id" : entity_e["_id"]
193
- }, {
194
- "$set" : entity
195
- })
196
-
197
- def _import_multiple(self, collection, data, key, policy = IGNORE):
189
+ if "_id" in entity:
190
+ del entity["_id"]
191
+ collection.update({"_id": entity_e["_id"]}, {"$set": entity})
192
+
193
+ def _import_multiple(self, collection, data, key, policy=IGNORE):
198
194
  # iterates over the complete set of data element to load
199
195
  # the JSON contents and then load the corresponding entity
200
196
  # value into the data source
@@ -211,60 +207,65 @@ class ExportManager(object):
211
207
  # that in case the underlying identifiers does not exists a
212
208
  # new value is generated using the pre-defined strategy
213
209
  if "_id" in entity:
214
- try: entity["_id"] = self.adapter.object_id(entity["_id"])
215
- except Exception: entity["_id"] = entity["_id"]
216
- else: entity["_id"] = self.adapter.object_id()
210
+ try:
211
+ entity["_id"] = self.adapter.object_id(entity["_id"])
212
+ except Exception:
213
+ entity["_id"] = entity["_id"]
214
+ else:
215
+ entity["_id"] = self.adapter.object_id()
217
216
 
218
217
  # retrieves the key value for the current entity to
219
218
  # be inserted and then tries to retrieve an existing
220
219
  # entity for the same key, to avoid duplicated entry
221
220
  value = entity.get(key, None)
222
- if value: entity_e = collection.find_one({key : value})
223
- else: entity_e = None
221
+ if value:
222
+ entity_e = collection.find_one({key: value})
223
+ else:
224
+ entity_e = None
224
225
 
225
226
  # in case there's no existing entity for the same key
226
227
  # (normal situation) only need to insert the new entity
227
228
  # otherwise must apply the selected conflict policy for
228
229
  # the resolution of the data source conflict
229
- if not entity_e: collection.insert(entity)
230
- elif policy == IGNORE: continue
230
+ if not entity_e:
231
+ collection.insert(entity)
232
+ elif policy == IGNORE:
233
+ continue
231
234
  elif policy == OVERWRITE:
232
- collection.remove({key : value})
235
+ collection.remove({key: value})
233
236
  collection.insert(entity)
234
237
  elif policy == DUPLICATE:
235
238
  collection.insert(entity)
236
239
  elif policy == JOIN:
237
- if "_id" in entity: del entity["_id"]
238
- collection.update({
239
- "_id" : entity_e["_id"]
240
- }, {
241
- "$set" : entity
242
- })
243
-
244
- def _export_single(self, collection, key = "_id", encoder = None):
240
+ if "_id" in entity:
241
+ del entity["_id"]
242
+ collection.update({"_id": entity_e["_id"]}, {"$set": entity})
243
+
244
+ def _export_single(self, collection, key="_id", encoder=None):
245
245
  entities = collection.find()
246
246
  _entities = {}
247
247
  for entity in entities:
248
248
  value = entity[key]
249
249
  value_s = self._to_key(value)
250
250
  _entities[value_s] = entity
251
- data = json.dumps(_entities, cls = encoder)
251
+ data = json.dumps(_entities, cls=encoder)
252
252
  data = legacy.bytes(data)
253
253
  return data
254
254
 
255
- def _export_multiple(self, collection, key = "_id", encoder = None):
255
+ def _export_multiple(self, collection, key="_id", encoder=None):
256
256
  entities = collection.find()
257
257
  for entity in entities:
258
258
  value = entity[key]
259
259
  value_s = self._to_key(value)
260
260
  value_s = self._escape_key(value_s)
261
- _data = json.dumps(entity, cls = encoder)
261
+ _data = json.dumps(entity, cls=encoder)
262
262
  _data = legacy.bytes(_data)
263
263
  yield (value_s, _data)
264
264
 
265
265
  def _to_key(self, key):
266
266
  key_t = type(key)
267
- if key_t in legacy.STRINGS: return key
267
+ if key_t in legacy.STRINGS:
268
+ return key
268
269
  key = legacy.UNICODE(key)
269
270
  return key
270
271
 
@@ -272,16 +273,15 @@ class ExportManager(object):
272
273
  return key.replace(":", "_")
273
274
 
274
275
  def _deploy_zip(self, zip_path, path):
275
- zip_file = zipfile.ZipFile(zip_path, mode = "r")
276
- try: zip_file.extractall(path)
277
- finally: zip_file.close()
276
+ zip_file = zipfile.ZipFile(zip_path, mode="r")
277
+ try:
278
+ zip_file.extractall(path)
279
+ finally:
280
+ zip_file.close()
278
281
 
279
282
  def _create_zip(self, zip_path, path):
280
283
  zip_file = zipfile.ZipFile(
281
- zip_path,
282
- mode = "w",
283
- compression = zipfile.ZIP_DEFLATED,
284
- allowZip64 = True
284
+ zip_path, mode="w", compression=zipfile.ZIP_DEFLATED, allowZip64=True
285
285
  )
286
286
 
287
287
  try:
@@ -290,20 +290,22 @@ class ExportManager(object):
290
290
  _path = os.path.join(path, name)
291
291
  is_file = os.path.isfile(_path)
292
292
 
293
- if is_file: zip_file.write(_path)
294
- else: self.__add_to_zip(zip_file, _path, base = path)
293
+ if is_file:
294
+ zip_file.write(_path)
295
+ else:
296
+ self.__add_to_zip(zip_file, _path, base=path)
295
297
  finally:
296
298
  zip_file.close()
297
299
 
298
- def __add_to_zip(self, zip_file, path, base = ""):
300
+ def __add_to_zip(self, zip_file, path, base=""):
299
301
  list = os.listdir(path)
300
302
  for name in list:
301
303
  _path = os.path.join(path, name)
302
- _path_out = _path[len(base):]
304
+ _path_out = _path[len(base) :]
303
305
  _path_out = _path_out.replace("\\", "/")
304
306
  _path_out = _path_out.strip("/")
305
307
 
306
308
  if os.path.isfile(_path):
307
309
  zip_file.write(_path, _path_out)
308
310
  elif os.path.isdir(_path):
309
- self.__add_to_zip(zip_file, _path, base = base)
311
+ self.__add_to_zip(zip_file, _path, base=base)