django-restit 4.2.42__py3-none-any.whl → 4.2.44__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.
account/rpc/group.py CHANGED
@@ -83,7 +83,7 @@ def rest_on_membership(request, pk=None):
83
83
  @rd.login_required
84
84
  def rest_on_users_membership(request, group_id=None):
85
85
  ms = request.member.getMembershipFor(group_id, include_parents=True)
86
- if ms is None:
86
+ if ms is None or not ms.is_enabled:
87
87
  return rv.restStatus(request, False, error="not found", error_code=404)
88
88
  return ms.restGet(request)
89
89
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-restit
3
- Version: 4.2.42
3
+ Version: 4.2.44
4
4
  Summary: A Rest Framework for DJANGO
5
5
  License: MIT
6
6
  Author: Ian Starnes
@@ -38,7 +38,7 @@ account/periodic.py,sha256=-u0n-7QTJgDOkasGhBAPwHAwjpqWGA-MZLEFkVTqCGU,874
38
38
  account/rpc/__init__.py,sha256=SGF0M_-H0dKh3b1apSX29BotNWAvITYccGQVC0MIjL8,336
39
39
  account/rpc/auth.py,sha256=eywdJSjsi_Ds2pM4wnltPJUfjIQqf6r6e99eKS7q3BA,15593
40
40
  account/rpc/device.py,sha256=fbbZFp3cUdhVXvD7gVFOqFWj4hKS3bjZKD_aF5fQxd8,2852
41
- account/rpc/group.py,sha256=JFOTgAbxtpmNmJIMb9Gqesd4y_31Sv9G6atkRoNylqs,3802
41
+ account/rpc/group.py,sha256=eW5p0TbJC7b77Xf7CTqLm-Qq_r1FPbGmSuVWrQR37uA,3823
42
42
  account/rpc/member.py,sha256=PU-Uz5KUI_BZFy-F-taDqAfnt_AwONYXSzUvfm7eyTw,1264
43
43
  account/rpc/notify.py,sha256=Q2YWejP36egeF060Hih5uX4Psv_B8NWlLLPi7iDYlIw,3344
44
44
  account/rpc/oauth.py,sha256=ISLVsR5HvKALANokaOFRvF4FTRxWtXPvVnZAYANKxpo,2864
@@ -134,7 +134,7 @@ location/providers/iplookup/extremeip.py,sha256=QNRGhwXXsOuJL2M-xiI2pFN_6LP2HkqS
134
134
  location/providers/iplookup/geoplugin.py,sha256=RK_6McxHYlVVMVdJ2rCafw-kqMfzMm3g_tJjBwcKXYg,2121
135
135
  location/providers/iplookup/ipapi.py,sha256=cyVs_n4GYvmLsPn8jDOcfevPzWkwBs22PSzoYRzVhDo,1797
136
136
  location/providers/iplookup/ipinfo.py,sha256=G3mrBQOAOzWkQBXf8uF98-xVPSA4HGAkYl4PlwmeKVU,1265
137
- location/providers/iplookup/restit.py,sha256=XgD3agvsfO_gL7As-UCava1gg3cShhvPKzUBSrGyQHw,937
137
+ location/providers/iplookup/restit.py,sha256=UJlQ_-X85YhyO4Yqt7ys8-MFY_zQcAKHecaIOxL844U,937
138
138
  location/providers/location/__init__.py,sha256=ki4sfPrgHMMr50GCKGZb2NDK0Unl8xkgcWJT7fsWgwA,42
139
139
  location/providers/location/google.py,sha256=RXZoYXUcTerE3-7z2BciEuDJJB-f-0_F6jWLnEK5v8w,2860
140
140
  location/providers/timezones/__init__.py,sha256=enslc1cVTju3GKrvpLoAxSHUKkLeREhed-eHkvHWdoM,46
@@ -359,7 +359,7 @@ pushit/utils.py,sha256=IeTCGa-164nmB1jIsK1lu1O1QzUhS3BKfuXHGjCW-ck,2121
359
359
  rest/.gitignore,sha256=TbEvWRMnAiajCTOdhiNrd9eeCAaIjRp9PRjE_VkMM5g,118
360
360
  rest/README.md,sha256=V3ETc-cJu8PZIbKr9xSe_pA4JEUpC8Dhw4bQeVCDJPw,5460
361
361
  rest/RemoteEvents.py,sha256=nL46U7AuxIrlw2JunphR1tsXyqi-ep_gD9CYGpYbNgE,72
362
- rest/__init__.py,sha256=2-UnT-DpX_VCvJoBb0q2uUn-JATRDQg-pEwLwkz3eM4,121
362
+ rest/__init__.py,sha256=D1F9OsFxtJr7AuWmena-TkvTjJPlbM2SRa6S8jjJtkk,121
363
363
  rest/arc4.py,sha256=y644IbF1ec--e4cUJ3KEYsewTCITK0gmlwa5mJruFC0,1967
364
364
  rest/cache.py,sha256=1Qg0rkaCJCaVP0-l5hZg2CIblTdeBSlj_0fP6vlKUpU,83
365
365
  rest/crypto/__init__.py,sha256=Tl0U11rgj1eBYqd6OXJ2_XSdNLumW_JkBZnaJqI6Ldw,72
@@ -440,17 +440,17 @@ taskqueue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
440
440
  taskqueue/admin.py,sha256=E6zXoToS_ea3MdoGjZzF1JiepWFtDSoZUQdan8H-pXI,208
441
441
  taskqueue/migrations/0001_initial.py,sha256=JwYib8CK5ftSXlfxKZUcKEEVsXktNB5q3h-2tu9inGk,4738
442
442
  taskqueue/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
443
- taskqueue/models.py,sha256=xt3WQD0QcMK4W6C4YMMD9Ok7H2fz2GWEaonpsPq6Akg,19306
443
+ taskqueue/models.py,sha256=tCFAKSr8JybUJV4gijg3wUCwQMJiHUsRBgHH2CWonfY,22119
444
444
  taskqueue/periodic.py,sha256=2i0271khrCow3hDmlNEcoAZnesBVl40jd7MIim2Cxs4,3543
445
445
  taskqueue/rpc.py,sha256=If5E9D9AR2RqW4lHRaDuD9L9b9ZfL_PaBQ6iX91ehvU,5736
446
446
  taskqueue/tq.py,sha256=PzSoDrawYcqZylruEgsK95gcJ4J_VhdM6rxg9V6_X8E,942
447
447
  taskqueue/transports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
448
448
  taskqueue/transports/email.py,sha256=H4GaomiyCck5R_AOcsrMawCl-_Bp_Zg-uWto9t1Xcoo,623
449
- taskqueue/transports/http.py,sha256=MIwB7e3duAv-xrBdncDkxqa4OKsKVwjdBscnrDUv4So,664
449
+ taskqueue/transports/http.py,sha256=kRBjHiwTmk5b4TMdZWt1EKKcjfSlX8DFmtmJaRGZQFw,681
450
450
  taskqueue/transports/s3.py,sha256=fMosL893u1iQdo6Y1djwb7KEoNo6TTsDPJl13OJdJP8,1913
451
451
  taskqueue/transports/sftp.py,sha256=jT1_krjTHA7DCAukD85aGYRCg9m0cEH9EWzOC-wJGdk,1891
452
452
  taskqueue/transports/sms.py,sha256=H1-LIGEMfbUNqJD9amRcsvKUSwtz9yBj1QNfB7EHjHE,142
453
- taskqueue/worker.py,sha256=Gry6ysDh34m4uB8mQsmyEyxl56p1hwlSUD5T1H2jl_w,15692
453
+ taskqueue/worker.py,sha256=u7H-FLkz7vpBoDaab9hpw4RduvG1ZTdtlw3PSHRBmUw,15737
454
454
  telephony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
455
455
  telephony/admin.py,sha256=iOdsBfFFbBisdqKSZ36bIrh_z5sU0Wx_PkaFi8wd1iA,243
456
456
  telephony/decorators.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -492,7 +492,7 @@ ws4redis/servers/uwsgi.py,sha256=VyhoCI1DnVFqBiJYHoxqn5Idlf6uJPHvfBKgkjs34mo,172
492
492
  ws4redis/settings.py,sha256=K0yBiLUuY81iDM4Yr-k8hbvjn5VVHu5zQhmMK8Dtz0s,1536
493
493
  ws4redis/utf8validator.py,sha256=S0OlfjeGRP75aO6CzZsF4oTjRQAgR17OWE9rgZdMBZA,5122
494
494
  ws4redis/websocket.py,sha256=R0TUyPsoVRD7Y_oU7w2I6NL4fPwiz5Vl94-fUkZgLHA,14848
495
- django_restit-4.2.42.dist-info/LICENSE.md,sha256=VHN4hhEeVOoFjtG-5fVv4jesA4SWi0Z-KgOzzN6a1ps,1068
496
- django_restit-4.2.42.dist-info/METADATA,sha256=33_hH1hxg3ZRJMY3EW2ePRnCcIuf4irKfwJu1SQHX1A,7594
497
- django_restit-4.2.42.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
498
- django_restit-4.2.42.dist-info/RECORD,,
495
+ django_restit-4.2.44.dist-info/LICENSE.md,sha256=VHN4hhEeVOoFjtG-5fVv4jesA4SWi0Z-KgOzzN6a1ps,1068
496
+ django_restit-4.2.44.dist-info/METADATA,sha256=ZgC_TvH6w7_xLrj9Anw73cJI9jNaC_dJ8AfuybTH6mw,7594
497
+ django_restit-4.2.44.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
498
+ django_restit-4.2.44.dist-info/RECORD,,
@@ -26,7 +26,7 @@ def getLocation(ip):
26
26
  if GEOIP_RESTIT_HOST is None:
27
27
  return None
28
28
  params = {"ip": ip}
29
- url = f"https://{GEOIP_RESTIT_HOST}/rpc/location/ip/lookup"
29
+ url = f"https://{GEOIP_RESTIT_HOST}/api/location/ip/lookup"
30
30
  res = requests.get(url, params=params)
31
31
  if res.status_code != 200:
32
32
  return None
rest/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from .uberdict import UberDict # noqa: F401
2
2
  from .settings_helper import settings # noqa: F401
3
3
 
4
- __version__ = "4.2.42"
4
+ __version__ = "4.2.44"
taskqueue/models.py CHANGED
@@ -31,6 +31,10 @@ TASK_STATES = [
31
31
  (TASK_STATE_CANCELED, 'canceled')
32
32
  ]
33
33
 
34
+ TQ_RETRY_BACKOFF_FACTOR = settings.get("TQ_RETRY_BACKOFF_FACTOR", 2)
35
+ TQ_RETRY_ATTEMPTS = settings.get("TQ_RETRY_ATTEMPTS", 5)
36
+ TQ_RETRY_DELAY = settings.get("TQ_RETRY_DELAY", 60)
37
+
34
38
  def getAppHandler(app_name, fname):
35
39
  try:
36
40
  # module = __import__(app_name + '.tq', globals(), locals(), ['*'], 0)
@@ -143,6 +147,12 @@ class Task(models.Model, RestModel):
143
147
  return self.runtime
144
148
  return (datetime.now() - self.started_at).total_seconds()
145
149
 
150
+ @property
151
+ def max_attempts(self):
152
+ if self.data:
153
+ return self.data.get("retry_max_attempts", TQ_RETRY_ATTEMPTS)
154
+ return TQ_RETRY_ATTEMPTS
155
+
146
156
  def set_action(self, value):
147
157
  if value == "retry_now":
148
158
  self.retry_now()
@@ -158,6 +168,20 @@ class Task(models.Model, RestModel):
158
168
 
159
169
  def log(self, text, kind="info"):
160
170
  TaskLog.Log(self, text, kind=kind)
171
+ if self.data and ((self.data.log_component and self.data.log_pk) or self.data.log_tid):
172
+ PLOG = self.getModel("auditlog", "PersistentLog")
173
+ level = 0
174
+ if kind == "exception":
175
+ level = 21
176
+ elif kind == "error":
177
+ level = 17
178
+ PLOG.log(message=text, action=f"taskqueue_{kind}",
179
+ level=level,
180
+ method=self.fname, path=self.model,
181
+ tid=self.data.log_tid,
182
+ component=self.data.log_component,
183
+ pkey=self.data.log_pk,
184
+ group=self.data.group_id)
161
185
 
162
186
  def log_exception(self, text, kind="exception"):
163
187
  self.log(str(text), kind=kind)
@@ -173,7 +197,17 @@ class Task(models.Model, RestModel):
173
197
  def retry_later(self, reason=None, from_now_secs=None):
174
198
  if reason:
175
199
  self.reason = reason
176
- if from_now_secs:
200
+ if from_now_secs == -1:
201
+ # allow backoff retry
202
+ if self.data:
203
+ bof = self.data.get("retry_bof", TQ_RETRY_BACKOFF_FACTOR)
204
+ delay = self.data.get("retry_delay", TQ_RETRY_DELAY)
205
+ else:
206
+ bof = TQ_RETRY_BACKOFF_FACTOR
207
+ delay = TQ_RETRY_DELAY
208
+ attempts = self.attempts - 1
209
+ from_now_secs = delay * (bof ** attempts)
210
+ if from_now_secs is not None:
177
211
  # this will not run the task again until after this time has been hit
178
212
  self.scheduled_for = datetime.now() + timedelta(seconds=from_now_secs)
179
213
  self.state = TASK_STATE_RETRY
@@ -200,24 +234,30 @@ class Task(models.Model, RestModel):
200
234
  self.notifyError()
201
235
  self.save()
202
236
 
203
- def notifyError(self, kind="Failure"):
204
- subject = "TaskQueue - {}".format(kind)
205
- handler = "unknown bg_handler"
206
- if self.data:
207
- handler = self.data.get("bg_handler")
208
- msg = "{}:{}<br>\n{}".format(self.model, handler, self.reason)
209
- # sms_msg = "{}\n{}".format(subject, msg)
210
- # Member.notifyWithPermission("taskqueue_alerts", subject, msg, sms_msg=sms_msg)
237
+ def notifyError(self):
238
+ handler = f"{self.model}{self.fname}"
239
+ subject = f"TaskQueue - {handler}"
240
+
241
+ msg = f"{handler}<br>\n{self.reason}"
211
242
  metadata = {
212
243
  "server": settings.get("HOSTNAME", "unknown"),
213
244
  "task": self.pk,
214
245
  "reason": self.reason,
215
- "kind": kind,
216
246
  "app": self.model,
217
247
  "fname": self.fname,
218
248
  "channel": self.channel,
249
+ "attempts": self.attempts,
219
250
  "handler": handler
220
251
  }
252
+
253
+ if self.data:
254
+ if self.data.url:
255
+ metadata["url"] = self.data.url
256
+ msg = f"{msg}<br>\n{self.data.url}"
257
+ if self.data.log_component:
258
+ metadata["component"] = self.data.log_component
259
+ if self.data.log_pk:
260
+ metadata["component_id"] = self.data.log_pk
221
261
  try:
222
262
  import incident
223
263
  incident.event_now(
@@ -254,10 +294,16 @@ class Task(models.Model, RestModel):
254
294
  return getattr(model, self.fname, None)
255
295
 
256
296
  @classmethod
257
- def WebRequest(cls, url, data, fname="POST", stale_after_seconds=0):
297
+ def WebRequest(cls, url, data, fname="POST", stale_after_seconds=0,
298
+ log_component=None, log_pk=None, log_tid=None):
258
299
  tdata = nobjict()
259
300
  tdata.url = url
260
301
  tdata.data = data
302
+ if log_component is not None:
303
+ tdata.log_component = log_component
304
+ tdata.log_pk = log_pk
305
+ if log_tid is not None:
306
+ tdata.log_tid = log_tid
261
307
  task = cls(channel="tq_hook", model="tq_web_request", fname=fname, data=tdata)
262
308
  if stale_after_seconds:
263
309
  task.stale_after = datetime.now() + timedelta(seconds=stale_after_seconds)
@@ -266,29 +312,41 @@ class Task(models.Model, RestModel):
266
312
  return task
267
313
 
268
314
  @classmethod
269
- def EmailRequest(cls, address, data, filename=None, subject=None):
315
+ def EmailRequest(cls, address, data, filename=None, subject=None,
316
+ log_component=None, log_pk=None, log_tid=None):
270
317
  tdata = nobjict()
271
318
  tdata.address = address
272
319
  tdata.filename = filename
273
320
  tdata.subject = subject
274
321
  tdata.data = data
322
+ if log_component is not None:
323
+ tdata.log_component = log_component
324
+ tdata.log_pk = log_pk
325
+ if log_tid is not None:
326
+ tdata.log_tid = log_tid
275
327
  task = cls(channel="tq_hook", model="tq_email_request", data=tdata)
276
328
  task.save()
277
329
  task.publish()
278
330
  return task
279
331
 
280
332
  @classmethod
281
- def SMSRequest(cls, phone, data):
333
+ def SMSRequest(cls, phone, data, log_component=None, log_pk=None, log_tid=None):
282
334
  tdata = nobjict()
283
335
  tdata.phone = phone
284
336
  tdata.data = data
337
+ if log_component is not None:
338
+ tdata.log_component = log_component
339
+ tdata.log_pk = log_pk
340
+ if log_tid is not None:
341
+ tdata.log_tid = log_tid
285
342
  task = cls(channel="tq_hook", model="tq_sms_request", data=tdata)
286
343
  task.save()
287
344
  task.publish()
288
345
  return task
289
346
 
290
347
  @classmethod
291
- def SFTPRequest(cls, host, data, filename, username, password):
348
+ def SFTPRequest(cls, host, data, filename, username, password,
349
+ log_component=None, log_pk=None, log_tid=None):
292
350
  tdata = nobjict()
293
351
  tdata.host = host
294
352
  tdata.filename = filename
@@ -297,13 +355,19 @@ class Task(models.Model, RestModel):
297
355
  tdata.username = username
298
356
  tdata.password = password
299
357
  tdata.data = data
358
+ if log_component is not None:
359
+ tdata.log_component = log_component
360
+ tdata.log_pk = log_pk
361
+ if log_tid is not None:
362
+ tdata.log_tid = log_tid
300
363
  task = cls(channel="tq_hook", model="tq_sftp_request", data=tdata)
301
364
  task.save()
302
365
  task.publish()
303
366
  return task
304
367
 
305
368
  @classmethod
306
- def S3Request(cls, bucket, data, folder, aws, secret, filename, when):
369
+ def S3Request(cls, bucket, data, folder, aws, secret, filename, when,
370
+ log_component=None, log_pk=None, log_tid=None):
307
371
  tdata = nobjict()
308
372
  tdata.bucket = bucket
309
373
  tdata.filename = filename
@@ -312,6 +376,11 @@ class Task(models.Model, RestModel):
312
376
  tdata.aws = aws
313
377
  tdata.secret = secret
314
378
  tdata.when = str(when)
379
+ if log_component is not None:
380
+ tdata.log_component = log_component
381
+ tdata.log_pk = log_pk
382
+ if log_tid is not None:
383
+ tdata.log_tid = log_tid
315
384
  task = cls(channel="tq_hook", model="tq_s3_request", data=tdata)
316
385
  task.save()
317
386
  task.publish()
@@ -14,7 +14,7 @@ def REQUEST(task):
14
14
  resp = net.REQUEST(method, url, params=params,
15
15
  data=task.data.data, raw_response=True,
16
16
  verify=False, timeout=REQ_TIMEOUT)
17
- task.log(resp.text)
17
+ task.log(resp.text, kind="response")
18
18
  return resp.status_code == 200
19
19
  except requests.Timeout:
20
20
  task.log("request timed out", kind="error")
taskqueue/worker.py CHANGED
@@ -178,7 +178,7 @@ class WorkManager(object):
178
178
  pass
179
179
 
180
180
  def processBacklog(self):
181
- tasks = Task.objects.filter(state__in=[0,1,2])
181
+ tasks = Task.objects.filter(state__in=[0, 1, 2])
182
182
  for task in tasks:
183
183
  if task.channel in self.subscribe_to:
184
184
  if task.cancel_requested:
@@ -196,8 +196,9 @@ class WorkManager(object):
196
196
  def _on_webrequest(self, task):
197
197
  if http.REQUEST(task):
198
198
  task.completed()
199
- elif task.attempts < 5:
200
- task.retry_later(from_now_secs=task.attempts * task.attempts * 60)
199
+ elif task.attempts < task.max_attempts:
200
+ # -1 will auto calculate retry with back off
201
+ task.retry_later(from_now_secs=-1)
201
202
  else:
202
203
  task.failed("max attempts")
203
204
 
@@ -212,8 +213,8 @@ class WorkManager(object):
212
213
  resp = s3.UPLOAD(task)
213
214
  if resp:
214
215
  task.completed()
215
- elif task.state == 1:
216
- task.retry_later(from_now_secs=task.attempts * 60)
216
+ elif task.attempts < task.max_attempts:
217
+ task.retry_later(from_now_secs=-1)
217
218
  else:
218
219
  task.failed()
219
220