squad 1.84__py3-none-any.whl → 1.86.3__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.
Potentially problematic release.
This version of squad might be problematic. Click here for more details.
- squad/api/__init__.py +40 -0
- squad/api/rest.py +1 -0
- squad/ci/backend/fake.py +6 -0
- squad/ci/backend/lava.py +6 -0
- squad/ci/backend/null.py +15 -1
- squad/ci/backend/tuxsuite.py +11 -0
- squad/ci/models.py +1 -1
- squad/frontend/templates/squad/testjobs.jinja2 +8 -6
- squad/settings.py +8 -11
- squad/version.py +1 -1
- {squad-1.84.dist-info → squad-1.86.3.dist-info}/METADATA +1 -1
- {squad-1.84.dist-info → squad-1.86.3.dist-info}/RECORD +16 -16
- {squad-1.84.dist-info → squad-1.86.3.dist-info}/COPYING +0 -0
- {squad-1.84.dist-info → squad-1.86.3.dist-info}/WHEEL +0 -0
- {squad-1.84.dist-info → squad-1.86.3.dist-info}/entry_points.txt +0 -0
- {squad-1.84.dist-info → squad-1.86.3.dist-info}/top_level.txt +0 -0
squad/api/__init__.py
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
from django.core.cache import cache
|
2
|
+
from rest_framework.throttling import UserRateThrottle
|
3
|
+
|
4
|
+
|
5
|
+
class SocialUserRateThrottle(UserRateThrottle):
|
6
|
+
"""
|
7
|
+
Limits the rate of API calls that may be made by a given social user.
|
8
|
+
|
9
|
+
The user id will be used as a unique cache key if the user is
|
10
|
+
authenticated. For anonymous requests, the IP address of the request will
|
11
|
+
be used.
|
12
|
+
"""
|
13
|
+
|
14
|
+
scope = "socialuser"
|
15
|
+
|
16
|
+
def is_social_user(self, user):
|
17
|
+
"""
|
18
|
+
Social account user might use multiple applications (github, gitlab, google, ...)
|
19
|
+
to log in. But all of the login applications would likely point to the same
|
20
|
+
django user, which is what we want to rate limit here.
|
21
|
+
"""
|
22
|
+
|
23
|
+
key = f"socialuser#{user.id}"
|
24
|
+
from allauth.socialaccount.models import SocialAccount
|
25
|
+
return cache.get_or_set(key, SocialAccount.objects.filter(user_id=user.id).exists())
|
26
|
+
|
27
|
+
def get_cache_key(self, request, view):
|
28
|
+
if request.user and request.user.is_authenticated:
|
29
|
+
if not self.is_social_user(request.user):
|
30
|
+
# do not throttle non-social users
|
31
|
+
return None
|
32
|
+
|
33
|
+
ident = request.user.pk
|
34
|
+
else:
|
35
|
+
ident = self.get_ident(request)
|
36
|
+
|
37
|
+
return self.cache_format % {
|
38
|
+
"scope": self.scope,
|
39
|
+
"ident": ident
|
40
|
+
}
|
squad/api/rest.py
CHANGED
@@ -173,6 +173,7 @@ class TestJobFilter(filters.FilterSet):
|
|
173
173
|
"fetched": ['exact', 'in'],
|
174
174
|
"fetch_attempts": ['exact', 'in'],
|
175
175
|
"last_fetch_attempt": ['exact', 'in', 'lt', 'gt', 'lte', 'gte'],
|
176
|
+
"created_at": ['exact', 'in', 'lt', 'gt', 'lte', 'gte'],
|
176
177
|
"failure": ['exact', 'in', 'startswith', 'contains', 'icontains'],
|
177
178
|
"can_resubmit": ['exact', 'in'],
|
178
179
|
"resubmitted_count": ['exact', 'in'],
|
squad/ci/backend/fake.py
CHANGED
@@ -60,6 +60,12 @@ class Backend(object):
|
|
60
60
|
def job_url(self, test_job):
|
61
61
|
return 'https://example.com/job/%s' % test_job.job_id
|
62
62
|
|
63
|
+
def has_resubmit(self):
|
64
|
+
return False
|
65
|
+
|
66
|
+
def has_cancel(self):
|
67
|
+
return True
|
68
|
+
|
63
69
|
def cancel(self, test_job):
|
64
70
|
return True
|
65
71
|
|
squad/ci/backend/lava.py
CHANGED
@@ -106,6 +106,9 @@ class Backend(BaseBackend):
|
|
106
106
|
return job_id
|
107
107
|
return [job_id]
|
108
108
|
|
109
|
+
def has_cancel(self):
|
110
|
+
return True
|
111
|
+
|
109
112
|
def cancel(self, test_job):
|
110
113
|
if test_job.submitted and test_job.job_id is not None:
|
111
114
|
return self.__cancel_job__(test_job.job_id)
|
@@ -329,6 +332,9 @@ class Backend(BaseBackend):
|
|
329
332
|
scheme = socket_url.scheme
|
330
333
|
return '%s://%s:%s' % (scheme, hostname, port)
|
331
334
|
|
335
|
+
def has_resubmit(self):
|
336
|
+
return True
|
337
|
+
|
332
338
|
def resubmit(self, test_job):
|
333
339
|
with self.handle_job_submission():
|
334
340
|
new_job_id_list = self.__resubmit__(test_job.job_id)
|
squad/ci/backend/null.py
CHANGED
@@ -8,7 +8,7 @@ logger = logging.getLogger('squad.ci.backend')
|
|
8
8
|
description = "None"
|
9
9
|
|
10
10
|
|
11
|
-
class Backend
|
11
|
+
class Backend:
|
12
12
|
|
13
13
|
"""
|
14
14
|
This is the interface that all backends must implement. Depending on the
|
@@ -39,6 +39,13 @@ class Backend(object):
|
|
39
39
|
"""
|
40
40
|
raise NotImplementedError
|
41
41
|
|
42
|
+
def has_resubmit(self):
|
43
|
+
"""
|
44
|
+
If the backend has a resubmit method implemented, override this to
|
45
|
+
return True.
|
46
|
+
"""
|
47
|
+
return False
|
48
|
+
|
42
49
|
def resubmit(self, test_job):
|
43
50
|
"""
|
44
51
|
Re-submits given test job to the backend service
|
@@ -84,6 +91,13 @@ class Backend(object):
|
|
84
91
|
"""
|
85
92
|
raise NotImplementedError
|
86
93
|
|
94
|
+
def has_cancel(self):
|
95
|
+
"""
|
96
|
+
If the backend has a cancel method implemented, override this to
|
97
|
+
return True.
|
98
|
+
"""
|
99
|
+
return False
|
100
|
+
|
87
101
|
def cancel(self, test_job):
|
88
102
|
"""
|
89
103
|
Cancels the job if the backend allows it. It will not raise any
|
squad/ci/backend/tuxsuite.py
CHANGED
@@ -32,6 +32,11 @@ requests_session = None
|
|
32
32
|
|
33
33
|
|
34
34
|
class Backend(BaseBackend):
|
35
|
+
def has_resubmit(self):
|
36
|
+
return False
|
37
|
+
|
38
|
+
def has_cancel(self):
|
39
|
+
return True
|
35
40
|
|
36
41
|
@staticmethod
|
37
42
|
def get_session():
|
@@ -414,6 +419,12 @@ class Backend(BaseBackend):
|
|
414
419
|
endpoint = f'groups/{tux_group}/projects/{tux_user}/{result_type.lower()}s/{tux_uid}/cancel'
|
415
420
|
url = urljoin(self.data.url, endpoint)
|
416
421
|
response = requests.post(url)
|
422
|
+
|
423
|
+
testjob.fetched = True
|
424
|
+
testjob.submitted = True
|
425
|
+
testjob.job_status = "Canceled"
|
426
|
+
testjob.save()
|
427
|
+
|
417
428
|
return response.status_code == 200
|
418
429
|
|
419
430
|
def supports_callbacks(self):
|
squad/ci/models.py
CHANGED
@@ -382,7 +382,7 @@ class TestJob(models.Model):
|
|
382
382
|
if self.job_status == "Canceled":
|
383
383
|
return False
|
384
384
|
|
385
|
-
if self.job_id is not None:
|
385
|
+
if self.job_id is not None and self.backend.get_implementation().has_cancel():
|
386
386
|
return self.backend.get_implementation().cancel(self)
|
387
387
|
|
388
388
|
self.fetched = True
|
@@ -56,7 +56,7 @@
|
|
56
56
|
<div class='pull-right clearfix' ng-controller='CancelController' title="{{ _('Cancel all jobs') }}">
|
57
57
|
<a class="btn" ng-click="cancel_all({{ build.id }})" ng-class="{'btn-info': !done, 'btn-success': done, 'btn-danger': error}" ng-disabled="done" >
|
58
58
|
<span ng-class="{'fa':true, 'fa-recycle':!done, 'fa-check': done && !error, 'fa-spin': loading, 'fa-close': error}" ng-disabled="done"></span>
|
59
|
-
{{ _('
|
59
|
+
{{ _('Cancel all jobs') }}
|
60
60
|
</a>
|
61
61
|
</div>
|
62
62
|
<br />
|
@@ -107,7 +107,7 @@
|
|
107
107
|
ng-class="{'fa':true, 'fa-recycle':!done, 'fa-check': done && !error, 'fa-spin': loading, 'fa-close': error}"
|
108
108
|
ng-disabled="done">
|
109
109
|
</span>
|
110
|
-
{{ _('
|
110
|
+
{{ _('manual fetch') }}
|
111
111
|
</a>
|
112
112
|
</div>
|
113
113
|
{% endif %}
|
@@ -122,11 +122,12 @@
|
|
122
122
|
ng-class="{'fa':true, 'fa-recycle':!done, 'fa-check': done && !error, 'fa-spin': loading, 'fa-close': error}"
|
123
123
|
ng-disabled="done">
|
124
124
|
</span>
|
125
|
-
{{ _('%s
|
125
|
+
{{ _('cancel %s') % testjob.backend.get_implementation().has_cancel() }}
|
126
126
|
</a>
|
127
127
|
</div>
|
128
128
|
{% endif %}
|
129
129
|
<div class='pull-right' ng-controller='ResubmitController'>
|
130
|
+
{% if testjob.backend.get_implementation().has_resubmit() %}
|
130
131
|
<a
|
131
132
|
class="btn"
|
132
133
|
ng-click="resubmit({{testjob.id}}, true)"
|
@@ -138,9 +139,10 @@
|
|
138
139
|
ng-disabled="done"
|
139
140
|
title="{{ _('Resubmit job no matter the status') }}">
|
140
141
|
</span>
|
141
|
-
{{ _('
|
142
|
+
{{ _('force resubmit') }}
|
142
143
|
</a>
|
143
|
-
{%
|
144
|
+
{% endif %}
|
145
|
+
{% if testjob.can_resubmit and testjob.backend.get_implementation().has_resubmit() %}
|
144
146
|
<a
|
145
147
|
class="btn"
|
146
148
|
ng-click="resubmit({{testjob.id}}, false)"
|
@@ -152,7 +154,7 @@
|
|
152
154
|
ng-disabled="done"
|
153
155
|
title="{{ _('Resubmit job') }}">
|
154
156
|
</span>
|
155
|
-
{{ _('
|
157
|
+
{{ _('resubmit') }}
|
156
158
|
</a>
|
157
159
|
{% endif %}
|
158
160
|
</div>
|
squad/settings.py
CHANGED
@@ -13,6 +13,7 @@ https://docs.djangoproject.com/en/1.9/ref/settings/
|
|
13
13
|
from celery.schedules import crontab
|
14
14
|
from django.conf import global_settings
|
15
15
|
from email.utils import parseaddr
|
16
|
+
from importlib.util import find_spec
|
16
17
|
from glob import glob
|
17
18
|
import contextlib
|
18
19
|
import json
|
@@ -55,30 +56,23 @@ ALLOWED_HOSTS = ['*']
|
|
55
56
|
|
56
57
|
# Application definition
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
imp.find_module('django_extensions')
|
59
|
+
django_extensions = None
|
60
|
+
if find_spec('django_extensions'):
|
61
61
|
django_extensions = 'django_extensions'
|
62
|
-
except ImportError:
|
63
|
-
django_extensions = None
|
64
62
|
|
65
63
|
django_toolbar = None
|
66
64
|
django_toolbar_middleware = None
|
67
|
-
|
68
|
-
|
65
|
+
django_toolbar_module_spec = find_spec('debug_toolbar')
|
66
|
+
if django_toolbar_module_spec:
|
69
67
|
DEBUG_TOOLBAR_CONFIG = {
|
70
68
|
'JQUERY_URL': '',
|
71
69
|
'SHOW_COLLAPSED': True,
|
72
70
|
'SHOW_TOOLBAR_CALLBACK': 'squad.frontend.utils.show_debug_toolbar',
|
73
71
|
}
|
74
72
|
|
75
|
-
import imp
|
76
|
-
imp.find_module('debug_toolbar')
|
77
73
|
django_toolbar = 'debug_toolbar'
|
78
74
|
django_toolbar_middleware = 'debug_toolbar.middleware.DebugToolbarMiddleware'
|
79
75
|
INTERNAL_IPS = ['127.0.0.1']
|
80
|
-
except ImportError:
|
81
|
-
pass
|
82
76
|
|
83
77
|
|
84
78
|
django_allauth_middleware = None
|
@@ -445,6 +439,9 @@ if SENTRY_DSN:
|
|
445
439
|
# Django's default is 2.5MB, which is a bit low
|
446
440
|
DATA_UPLOAD_MAX_MEMORY_SIZE = 10485760 # 10MB
|
447
441
|
|
442
|
+
# Django requires that this specification is present in settings.py
|
443
|
+
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
444
|
+
|
448
445
|
try:
|
449
446
|
from squad.local_settings import * # noqa: F401,F403
|
450
447
|
except ImportError:
|
squad/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '1.
|
1
|
+
__version__ = '1.86.3'
|
@@ -7,17 +7,17 @@ squad/http.py,sha256=KuIKtpf3yOvf5fwc0T2MR0ul1l4AKxq3b0CLdk6KBhM,3667
|
|
7
7
|
squad/jinja2.py,sha256=OKX-lzNz6qtTZL56HWv4UBMPuBl4WQXv0qFJztGp9zs,2541
|
8
8
|
squad/mail.py,sha256=xH5wuIpD7u1fTN9vNOcbzByojleaffsKwp-9i3BeOD0,390
|
9
9
|
squad/manage.py,sha256=Z-LXT67p0R-IzwJ9fLIAacEZmU0VUjqDOSg7j2ZSxJ4,1437
|
10
|
-
squad/settings.py,sha256=
|
10
|
+
squad/settings.py,sha256=YB2g6mHaa4sct04u7DHGr_RSLugxMTDGaMnZl69Yp7o,14652
|
11
11
|
squad/socialaccount.py,sha256=vySqPwQ3qVVpahuJ-Snln8K--yzRL3bw4Nx27AsB39A,789
|
12
12
|
squad/urls.py,sha256=JiEfVW8YlzLPE52c2aHzdn5kVVKK4o22w8h5KOA6QhQ,2776
|
13
|
-
squad/version.py,sha256=
|
13
|
+
squad/version.py,sha256=Zroio3ZOXQsWya00gzHIk2KPUahZ7osQXHfabhsnwPw,23
|
14
14
|
squad/wsgi.py,sha256=SF8T0cQ0OPVyuYjO5YXBIQzvSXQHV0M2BTmd4gP1rPs,387
|
15
|
-
squad/api/__init__.py,sha256=
|
15
|
+
squad/api/__init__.py,sha256=CJiVakfAlHVN5mIFRVQYZQfuNUhUgWVbsdYTME4tq7U,1349
|
16
16
|
squad/api/apps.py,sha256=Trk72p-iV1uGn0o5mdJn5HARUoHGbfgO49jwXvpkmdQ,141
|
17
17
|
squad/api/ci.py,sha256=ymG-eMKXpJgrVUiZcqJW-dYZQKvm1LkdR3TUMe4OSoM,6943
|
18
18
|
squad/api/data.py,sha256=obKDV0-neEvj5lPF9VED2gy_hpfhGtLJABYvSY38ing,2379
|
19
19
|
squad/api/filters.py,sha256=Zvp8DCJmiNquFWqvfVseEAAMYYPiT95RUjqKdzcqSnw,6917
|
20
|
-
squad/api/rest.py,sha256=
|
20
|
+
squad/api/rest.py,sha256=X3WX6tkqWl2H59fCJCNc3NIEkP4GoXImQLyCmvUlrMQ,77172
|
21
21
|
squad/api/urls.py,sha256=rmsdaL1uOCVSZ5x1redup9RliICmijaBjRK5ObsTkG8,1343
|
22
22
|
squad/api/utils.py,sha256=Sa8QFId3_oSqD2UOoY3Kuh54LLDLPNMq2sub5ktd6Fs,1160
|
23
23
|
squad/api/views.py,sha256=kuFlbiyZiD0i9jwwmkL3Y22LwJ3bx2oJs28d1g2DPA0,3898
|
@@ -25,14 +25,14 @@ squad/ci/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
squad/ci/admin.py,sha256=7yB-6F0cvt0NVvzGOTlZCyGPV_YHarmbKJZTTzataT4,2255
|
26
26
|
squad/ci/apps.py,sha256=6OVnzTdJkxdqEJnKWYE9dZgUcc29_T1LrDw41cK4EQk,139
|
27
27
|
squad/ci/exceptions.py,sha256=a1sccygniTYDSQi7FRn_6doapddFFiMf55AwGUh5Y80,227
|
28
|
-
squad/ci/models.py,sha256=
|
28
|
+
squad/ci/models.py,sha256=Fm-4b3SDgMh9HXzqjOd4iZDRMJ1D9AnZ2cg7i2OR248,16018
|
29
29
|
squad/ci/tasks.py,sha256=xoiOyh0HKLiKsAnQbolMRq4E9RcvP4xFgR0S9d_bgm4,3782
|
30
30
|
squad/ci/utils.py,sha256=38zHpw8xkZDSFlkG-2BwSK6AkcddK9OkN9LXuQ3SHR0,97
|
31
31
|
squad/ci/backend/__init__.py,sha256=yhpotXT9F4IdAOXvGQ3-17eOHAFwoaqf9SnMX17ab30,534
|
32
|
-
squad/ci/backend/fake.py,sha256=
|
33
|
-
squad/ci/backend/lava.py,sha256=
|
34
|
-
squad/ci/backend/null.py,sha256=
|
35
|
-
squad/ci/backend/tuxsuite.py,sha256=
|
32
|
+
squad/ci/backend/fake.py,sha256=9sPKndsGd5GDNPp35v-zfJWXZCbge-yXH3RBQGgTlPk,2340
|
33
|
+
squad/ci/backend/lava.py,sha256=EXwEksjdOi_ZrUoMkBTyxVjqVOnJvEFNg_LWqUKaIgA,33607
|
34
|
+
squad/ci/backend/null.py,sha256=0CVylWELIZw3JyzCROB4XXAjgQUi15YjQz5caRfTNBo,5434
|
35
|
+
squad/ci/backend/tuxsuite.py,sha256=Gq4cbmCRKglKSFL2ltH4vNkUTigmZnIO_8FZH6OJnPg,17521
|
36
36
|
squad/ci/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
squad/ci/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
squad/ci/management/commands/create_tuxsuite_boot_tests.py,sha256=JvjNusebLX71eyz9d-kaeCyekYSpzc1eXoeIqWK9ygo,4045
|
@@ -394,7 +394,7 @@ squad/frontend/templates/squad/test_run_suite_metrics.jinja2,sha256=WGjlObw7ZTGo
|
|
394
394
|
squad/frontend/templates/squad/test_run_suite_test_details.jinja2,sha256=HGGnxDoFpyPgiH34aIVRrQysLn7KLYtDITUeQikYOoY,5657
|
395
395
|
squad/frontend/templates/squad/test_run_suite_tests.jinja2,sha256=S5VJMIoc18W46iHtSSLYC_3C3Wj1saXU83wR-JvF8GI,935
|
396
396
|
squad/frontend/templates/squad/testjob.jinja2,sha256=hQLavgkYJ3qAKJMG7cHnmJGC1jdwCnox2w9oQvLzn7U,324
|
397
|
-
squad/frontend/templates/squad/testjobs.jinja2,sha256=
|
397
|
+
squad/frontend/templates/squad/testjobs.jinja2,sha256=a90ltfoIWORB4i1mubA3cfQzX1IoSMqhYpAUc38RZSk,9632
|
398
398
|
squad/frontend/templates/squad/testjobs_progress.jinja2,sha256=4_o53GOdcClRdiNQxPHwvXPI9Ia07gTJRu5SGrCJ7s4,2638
|
399
399
|
squad/frontend/templates/squad/tests-details-nav.jinja2,sha256=WDi4vf0ctRK1dK1Z3IirBuyn5Dq9_qg_9A1P3GrB31U,664
|
400
400
|
squad/frontend/templates/squad/tests.jinja2,sha256=2AaEoCHJiCzXu_36XOq0ihiGqxh_2U2w88dheBlIwy8,4970
|
@@ -431,9 +431,9 @@ squad/run/__main__.py,sha256=DOl8JOi4Yg7DdtwnUeGqtYBJ6P2k-D2psAEuYOjWr8w,66
|
|
431
431
|
squad/run/listener.py,sha256=jBeOQhPGb4EdIREB1QsCzYuumsfJ-TqJPd3nR-0m59g,200
|
432
432
|
squad/run/scheduler.py,sha256=CDJG3q5C0GuQuxwlMOfWTSSJpDdwbR6rzpbJfuA0xuw,277
|
433
433
|
squad/run/worker.py,sha256=jtML0h5qKDuSbpJ6_rpWP4MT_rsGA7a24AhwGxBquzk,594
|
434
|
-
squad-1.
|
435
|
-
squad-1.
|
436
|
-
squad-1.
|
437
|
-
squad-1.
|
438
|
-
squad-1.
|
439
|
-
squad-1.
|
434
|
+
squad-1.86.3.dist-info/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
435
|
+
squad-1.86.3.dist-info/METADATA,sha256=EnJrMFG-4ivsJncbuLs1S-_wOSjgR45ViaH0i6Og76E,1236
|
436
|
+
squad-1.86.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
437
|
+
squad-1.86.3.dist-info/entry_points.txt,sha256=apCDQydHZtvqV334ql6NhTJUAJeZRdtAm0TVcbbAi5Q,194
|
438
|
+
squad-1.86.3.dist-info/top_level.txt,sha256=_x9uqE1XppiiytmVTl_qNgpnXus6Gsef69HqfliE7WI,6
|
439
|
+
squad-1.86.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|