squad 1.87__py3-none-any.whl → 1.89__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
squad/api/rest.py CHANGED
@@ -1190,7 +1190,13 @@ class BuildViewSet(NestedViewSetMixin, ModelViewSet):
1190
1190
  raise ValidationError('url is required.')
1191
1191
  return Response({'message': 'OK'}, status=status.HTTP_202_ACCEPTED)
1192
1192
  except (ValidationError, IntegrityError) as e:
1193
- return Response({'message': ', '.join(e.messages)}, status=status.HTTP_400_BAD_REQUEST)
1193
+ message = ""
1194
+ if hasattr(e, "messages"):
1195
+ message = ', '.join(e.messages)
1196
+ else:
1197
+ message = str(e)
1198
+
1199
+ return Response({'message': message}, status=status.HTTP_400_BAD_REQUEST)
1194
1200
 
1195
1201
  @action(detail=True, methods=['get'], suffix='compare')
1196
1202
  def compare(self, request, pk=None):
squad/ci/backend/lava.py CHANGED
@@ -396,9 +396,10 @@ class Backend(BaseBackend):
396
396
 
397
397
  def __lava_job_name(self, definition):
398
398
  yaml_definition = yaml.safe_load(definition)
399
- if 'job_name' in yaml_definition.keys():
399
+ if type(yaml_definition) is dict and 'job_name' in yaml_definition.keys():
400
+ job_name = yaml_definition['job_name']
400
401
  # only return first 255 characters
401
- return yaml_definition['job_name'][:255]
402
+ return job_name[:255] if job_name else ''
402
403
  return None
403
404
 
404
405
  def __resubmit__(self, job_id):
@@ -659,11 +660,13 @@ class Backend(BaseBackend):
659
660
  suite = result['suite'].split("_", 1)[-1]
660
661
  res_name = "%s/%s" % (suite, result['name'])
661
662
  res_log = None
662
- if 'log_start_line' in result.keys() and \
663
- 'log_end_line' in result.keys() and \
664
- result['log_start_line'] is not None and \
665
- result['log_end_line'] is not None:
666
- res_log = self.__download_test_log__(raw_logs, result['log_start_line'], result['log_end_line'])
663
+ if 'log_start_line' in result.keys():
664
+ log_url = f"{self.job_url(test_job)}#L{result['log_start_line']}"
665
+ res_log = f"Testcase log: <a href='{log_url}'>{log_url}</a>\n"
666
+ if 'log_end_line' in result.keys() and \
667
+ result['log_start_line'] is not None and \
668
+ result['log_end_line'] is not None:
669
+ res_log += self.__download_test_log__(raw_logs, result['log_start_line'], result['log_end_line'])
667
670
  # YAML from LAVA has all values serialized to strings
668
671
  if result['measurement'] == 'None' or result['measurement'] is None:
669
672
  res_value = result['result']
@@ -332,7 +332,14 @@ class Backend(BaseBackend):
332
332
  test_job.name = ','.join(results['tests'])
333
333
 
334
334
  if results['results'] == {}:
335
- test_job.failure = 'build failed'
335
+ waiting_for = results.get('waiting_for')
336
+ if waiting_for is None:
337
+ test_job.failure = 'no results'
338
+ elif 'BUILD' in waiting_for:
339
+ test_job.failure = 'build failed'
340
+ else:
341
+ test_job.failure = 'sanity test failed'
342
+
336
343
  return status, completed, metadata, tests, metrics, logs
337
344
 
338
345
  # Fetch results even if the job fails, but has results
squad/ci/tasks.py CHANGED
@@ -27,8 +27,12 @@ def poll(backend_id=None):
27
27
  @celery.task
28
28
  def fetch(job_id):
29
29
  logger.info("fetching %s" % job_id)
30
- backend = TestJob.objects.get(pk=job_id).backend
31
- backend.fetch(job_id)
30
+ try:
31
+ testjob = TestJob.objects.get(pk=job_id)
32
+ if testjob.job_id:
33
+ testjob.backend.fetch(testjob.id)
34
+ except TestJob.DoesNotExist:
35
+ return
32
36
 
33
37
 
34
38
  @celery.task
squad/core/callback.py CHANGED
@@ -56,12 +56,18 @@ def dispatch_callback(callback_object):
56
56
  else:
57
57
  args['data'] = json.loads(callback_object.payload)
58
58
 
59
- request = getattr(requests, callback_object.method)
60
- response = request(callback_object.url, **args)
59
+ try:
60
+ request = getattr(requests, callback_object.method)
61
+ response = request(callback_object.url, **args)
62
+ response_code = response.status_code
63
+ response_content = response.content
64
+ except requests.exceptions.RequestException as e:
65
+ response_code = None
66
+ response_content = str(e)
61
67
 
62
68
  if callback_object.record_response:
63
- callback_object.response_code = response.status_code
64
- callback_object.response_content = response.content
69
+ callback_object.response_code = response_code
70
+ callback_object.response_content = response_content
65
71
 
66
72
  callback_object.is_sent = True
67
73
  callback_object.save()
squad/core/history.py CHANGED
@@ -3,7 +3,7 @@ from django.core.paginator import Paginator
3
3
 
4
4
  from squad.core.queries import test_confidence
5
5
  from squad.core.utils import parse_name
6
- from squad.core.models import SuiteMetadata, KnownIssue, Environment
6
+ from squad.core.models import SuiteMetadata, KnownIssue, Environment, Build
7
7
 
8
8
 
9
9
  class TestResult(object):
@@ -49,6 +49,9 @@ class TestHistory(object):
49
49
  self.number = page
50
50
  builds = self.paginator.page(page)
51
51
 
52
+ if len(builds) == 0:
53
+ raise Build.DoesNotExist
54
+
52
55
  self.top = builds[0]
53
56
 
54
57
  issues_by_env = {}
squad/core/models.py CHANGED
@@ -16,7 +16,7 @@ from django.db.models.query import prefetch_related_objects
16
16
  from django.contrib.auth.models import User, AnonymousUser, Group as auth_group
17
17
  from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
18
18
  from django.contrib.contenttypes.models import ContentType
19
- from django.db.models.signals import post_save, pre_delete
19
+ from django.db.models.signals import post_save, pre_delete, pre_save
20
20
  from django.dispatch import receiver
21
21
 
22
22
  from django.conf import settings
@@ -1428,9 +1428,13 @@ class ProjectStatus(models.Model, TestSummaryBase):
1428
1428
  return None
1429
1429
 
1430
1430
  def __get_yaml_field__(self, field_value):
1431
- if field_value is not None:
1431
+ if field_value is None:
1432
+ return {}
1433
+
1434
+ try:
1432
1435
  return yaml.load(field_value, Loader=yaml.Loader)
1433
- return {}
1436
+ except yaml.YAMLError:
1437
+ return {}
1434
1438
 
1435
1439
  def get_regressions(self):
1436
1440
  return self.__get_yaml_field__(self.regressions)
@@ -1467,6 +1471,14 @@ class ProjectStatus(models.Model, TestSummaryBase):
1467
1471
  return thresholds_exceeded
1468
1472
 
1469
1473
 
1474
+ @receiver(pre_save, sender=ProjectStatus)
1475
+ def validate_project_status(sender, instance, *args, **kwargs):
1476
+ yaml_validator(instance.regressions)
1477
+ yaml_validator(instance.fixes)
1478
+ yaml_validator(instance.metric_regressions)
1479
+ yaml_validator(instance.metric_fixes)
1480
+
1481
+
1470
1482
  class NotificationDelivery(models.Model):
1471
1483
 
1472
1484
  status = models.ForeignKey('ProjectStatus', related_name='deliveries', on_delete=models.CASCADE)
squad/core/utils.py CHANGED
@@ -67,7 +67,7 @@ def yaml_validator(value):
67
67
  if len(value) == 0:
68
68
  return
69
69
  try:
70
- if not isinstance(yaml.safe_load(value), dict):
70
+ if not isinstance(yaml.load(value, Loader=yaml.Loader), dict):
71
71
  raise ValidationError("Dictionary object expected")
72
72
  except yaml.YAMLError as e:
73
73
  raise ValidationError(e)
@@ -3,6 +3,7 @@ from functools import reduce
3
3
  from django.shortcuts import render, get_object_or_404
4
4
  from django.core.paginator import Paginator
5
5
  from django.db.models import Q, Prefetch
6
+ from django.http import HttpResponseNotFound
6
7
 
7
8
  from squad.core.models import Project, Group, Build
8
9
  from squad.core.comparison import TestComparison, MetricComparison
@@ -107,7 +108,11 @@ def compare_builds(request):
107
108
  comparison = None
108
109
  project = None
109
110
  if project_slug:
110
- group_slug, project_slug = project_slug.split('/')
111
+ group_and_project = project_slug.split('/')
112
+ if len(group_and_project) != 2:
113
+ return HttpResponseNotFound()
114
+
115
+ group_slug, project_slug = group_and_project
111
116
  project = get_object_or_404(Project, group__slug=group_slug, slug=project_slug)
112
117
 
113
118
  baseline_build = request.GET.get('baseline')
@@ -37,7 +37,7 @@
37
37
  {% for status in test %}
38
38
  <td class="{{status[0]}}"><a href="{{ test_history_url }}">{{status[0]}}{% if status[1] %} ({{status[1]}} %){% endif %}</a>
39
39
  {% if status[2] %}
40
- <a href='#' data-toggle="modal" data-target="#info_modal" data-status="{{ status[1] }}"><span data-toggle="tooltip" data-placement="right" title="{{ _('Show info') }}" class='fa fa-info-circle'></span></a>
40
+ <a href='#' data-toggle="modal" data-target="#info_modal" data-status="{{ status[2] }}"><span data-toggle="tooltip" data-placement="right" title="{{ _('Show info') }}" class='fa fa-info-circle'></span></a>
41
41
  {% endif %}
42
42
  </td>
43
43
  {% endfor %}
squad/frontend/tests.py CHANGED
@@ -6,7 +6,7 @@ from django.shortcuts import render, get_object_or_404
6
6
  from django.http import Http404
7
7
 
8
8
  from squad.http import auth
9
- from squad.core.models import Test, Suite, SuiteMetadata, Environment
9
+ from squad.core.models import Build, Test, Suite, SuiteMetadata, Environment
10
10
  from squad.core.history import TestHistory
11
11
  from squad.core.queries import test_confidence
12
12
  from squad.frontend.views import get_build
@@ -234,5 +234,5 @@ def test_history(request, group_slug, project_slug, build_version=None, testrun_
234
234
  history = TestHistory(project, full_test_name, top=top, page=page)
235
235
  context.update({"history": history})
236
236
  return render(request, 'squad/test_history.jinja2', context)
237
- except (Suite.DoesNotExist, SuiteMetadata.DoesNotExist) as e:
237
+ except (Suite.DoesNotExist, SuiteMetadata.DoesNotExist, Build.DoesNotExist) as e:
238
238
  raise Http404(f"Test not found: {e}")
@@ -4,26 +4,28 @@ import re
4
4
  from collections import defaultdict
5
5
  from squad.plugins import Plugin as BasePlugin
6
6
  from squad.core.models import SuiteMetadata
7
+ from django.template.defaultfilters import slugify
7
8
 
8
9
 
9
10
  logger = logging.getLogger()
10
11
 
11
12
  REGEX_NAME = 0
12
13
  REGEX_BODY = 1
14
+ REGEX_EXTRACT_NAME = 2
13
15
 
14
16
  MULTILINERS = [
15
- ('check-kernel-exception', r'-+\[? cut here \]?-+.*?-+\[? end trace \w* \]?-+'),
16
- ('check-kernel-kasan', r'=+\n\[[\s\.\d]+\]\s+BUG: KASAN:.*?=+'),
17
- ('check-kernel-kfence', r'=+\n\[[\s\.\d]+\]\s+BUG: KFENCE:.*?=+'),
17
+ ('check-kernel-exception', r'-+\[? cut here \]?-+.*?-+\[? end trace \w* \]?-+', r"\d][^\+\n]*"),
18
+ ('check-kernel-kasan', r'=+\n\[[\s\.\d]+\]\s+BUG: KASAN:.*?=+', r"BUG: KASAN:[^\+\n]*"),
19
+ ('check-kernel-kfence', r'=+\n\[[\s\.\d]+\]\s+BUG: KFENCE:.*?=+', r"BUG: KFENCE:[^\+\n]*"),
18
20
  ]
19
21
 
20
22
  ONELINERS = [
21
- ('check-kernel-oops', r'^[^\n]+Oops(?: -|:).*?$'),
22
- ('check-kernel-fault', r'^[^\n]+Unhandled fault.*?$'),
23
- ('check-kernel-warning', r'^[^\n]+WARNING:.*?$'),
24
- ('check-kernel-bug', r'^[^\n]+(?: kernel BUG at|BUG:).*?$'),
25
- ('check-kernel-invalid-opcode', r'^[^\n]+invalid opcode:.*?$'),
26
- ('check-kernel-panic', r'Kernel panic - not syncing.*?$'),
23
+ ('check-kernel-oops', r'^[^\n]+Oops(?: -|:).*?$', r"Oops[^\+\n]*"),
24
+ ('check-kernel-fault', r'^[^\n]+Unhandled fault.*?$', r"Unhandled [^\+\n]*"),
25
+ ('check-kernel-warning', r'^[^\n]+WARNING:.*?$', r"WARNING: [^\+\n]*"),
26
+ ('check-kernel-bug', r'^[^\n]+(?: kernel BUG at|BUG:).*?$', r"BUG[^\+\n]*"),
27
+ ('check-kernel-invalid-opcode', r'^[^\n]+invalid opcode:.*?$', r"invalid opcode: [^\+\n]*"),
28
+ ('check-kernel-panic', r'Kernel panic - not syncing.*?$', r"Kernel [^\+\n]*"),
27
29
  ]
28
30
 
29
31
  # Tip: broader regexes should come first
@@ -70,33 +72,55 @@ class Plugin(BasePlugin):
70
72
  snippets[regex_id].append(match[regex_id])
71
73
  return snippets
72
74
 
73
- def __create_tests(self, testrun, suite, test_name, lines):
75
+ def __create_tests(self, testrun, suite, test_name, lines, test_regex=None):
74
76
  """
75
77
  There will be at least one test per regex. If there were any match for a given
76
78
  regex, then a new test will be generated using test_name + shasum. This helps
77
79
  comparing kernel logs accross different builds
78
80
  """
79
- metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=test_name, kind='test')
80
- testrun.tests.create(
81
- suite=suite,
82
- result=(len(lines) == 0),
83
- log='\n'.join(lines),
84
- metadata=metadata,
85
- build=testrun.build,
86
- environment=testrun.environment,
87
- )
88
-
89
- # Some lines of the matched regex might be the same, and we don't want to create
90
- # multiple tests like test1-sha1, test1-sha1, etc, so we'll create a set of sha1sums
91
- # then create only new tests for unique sha's
81
+ # Run the REGEX_EXTRACT_NAME regex over the log lines to sort them by
82
+ # extracted name. If no name is extracted or the log parser did not
83
+ # have any output for a particular regex, just use the default name
84
+ # (for example "check-kernel-oops").
85
+ tests_to_create = defaultdict(set)
92
86
  shas = defaultdict(set)
93
- for line in lines:
94
- sha = self.__create_shasum(line)
95
- shas[sha].add(line)
96
87
 
97
- for sha, lines in shas.items():
98
- name = f'{test_name}-{sha}'
88
+ # If there are no lines, use the default name and create a passing
89
+ # test. For example "check-kernel-oops"
90
+ if not lines:
91
+ tests_to_create[test_name] = []
92
+
93
+ # If there are lines, then create the tests for these.
94
+ for line in lines:
95
+ extracted_name = self.__create_name(line, test_regex)
96
+ if extracted_name:
97
+ extended_test_name = f"{test_name}-{extracted_name}"
98
+ else:
99
+ extended_test_name = test_name
100
+ tests_to_create[extended_test_name].add(line)
101
+
102
+ for name, lines in tests_to_create.items():
99
103
  metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=name, kind='test')
104
+ testrun.tests.create(
105
+ suite=suite,
106
+ result=(len(lines) == 0),
107
+ log='\n'.join(lines),
108
+ metadata=metadata,
109
+ build=testrun.build,
110
+ environment=testrun.environment,
111
+ )
112
+
113
+ # Some lines of the matched regex might be the same, and we don't want to create
114
+ # multiple tests like test1-sha1, test1-sha1, etc, so we'll create a set of sha1sums
115
+ # then create only new tests for unique sha's
116
+
117
+ for line in lines:
118
+ sha = self.__create_shasum(line)
119
+ name_with_sha = f"{name}-{sha}"
120
+ shas[name_with_sha].add(line)
121
+
122
+ for name_with_sha, lines in shas.items():
123
+ metadata, _ = SuiteMetadata.objects.get_or_create(suite=suite.slug, name=name_with_sha, kind='test')
100
124
  testrun.tests.create(
101
125
  suite=suite,
102
126
  result=False,
@@ -106,11 +130,30 @@ class Plugin(BasePlugin):
106
130
  environment=testrun.environment,
107
131
  )
108
132
 
133
+ def __remove_numbers_and_time(self, snippet):
134
+ without_numbers = re.sub(r"(0x[a-f0-9]+|[<\[][0-9a-f]+?[>\]]|\d+)", "", snippet)
135
+ without_time = re.sub(r"^\[[^\]]+\]", "", without_numbers)
136
+
137
+ return without_time
138
+
139
+ def __create_name(self, snippet, regex=None):
140
+ matches = None
141
+ if regex:
142
+ matches = regex.findall(snippet)
143
+ if not matches:
144
+ return None
145
+ snippet = matches[0]
146
+ without_numbers_and_time = self.__remove_numbers_and_time(snippet)
147
+
148
+ # Limit the name length to 191 characters, since the max name length
149
+ # for SuiteMetadata in SQUAD is 256 characters. The SHA and "-" take 65
150
+ # characters: 256-65=191
151
+ return slugify(without_numbers_and_time)[:191]
152
+
109
153
  def __create_shasum(self, snippet):
110
154
  sha = hashlib.sha256()
111
- without_numbers = re.sub(r'(0x[a-f0-9]+|[<\[][0-9a-f]+?[>\]]|\d+)', '', snippet)
112
- without_time = re.sub(r'^\[[^\]]+\]', '', without_numbers)
113
- sha.update(without_time.encode())
155
+ without_numbers_and_time = self.__remove_numbers_and_time(snippet)
156
+ sha.update(without_numbers_and_time.encode())
114
157
  return sha.hexdigest()
115
158
 
116
159
  def postprocess_testrun(self, testrun):
@@ -133,4 +176,8 @@ class Plugin(BasePlugin):
133
176
 
134
177
  for regex_id in range(len(REGEXES)):
135
178
  test_name = REGEXES[regex_id][REGEX_NAME]
136
- self.__create_tests(testrun, suite, test_name, snippets[regex_id])
179
+ regex_pattern = REGEXES[regex_id][REGEX_EXTRACT_NAME]
180
+ test_name_regex = None
181
+ if regex_pattern:
182
+ test_name_regex = re.compile(regex_pattern, re.S | re.M)
183
+ self.__create_tests(testrun, suite, test_name, snippets[regex_id], test_name_regex)
squad/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.87'
1
+ __version__ = '1.89'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: squad
3
- Version: 1.87
3
+ Version: 1.89
4
4
  Summary: Software Quality Dashboard
5
5
  Home-page: https://github.com/Linaro/squad
6
6
  Author: Antonio Terceiro
@@ -10,14 +10,14 @@ squad/manage.py,sha256=Z-LXT67p0R-IzwJ9fLIAacEZmU0VUjqDOSg7j2ZSxJ4,1437
10
10
  squad/settings.py,sha256=CRmnXFDrfdspzXGUIlffRcKMQizJ4Wzyyg1cIRu-h-M,14535
11
11
  squad/socialaccount.py,sha256=vySqPwQ3qVVpahuJ-Snln8K--yzRL3bw4Nx27AsB39A,789
12
12
  squad/urls.py,sha256=JiEfVW8YlzLPE52c2aHzdn5kVVKK4o22w8h5KOA6QhQ,2776
13
- squad/version.py,sha256=Xp5Lfh3Rguz_dG-kSYMkDDH_JfdlrBGqdkYAK12o7fk,21
13
+ squad/version.py,sha256=DHemnt4WEI99t3epDIiaS6j6mPKaFVroxzlr9RNdMCU,21
14
14
  squad/wsgi.py,sha256=SF8T0cQ0OPVyuYjO5YXBIQzvSXQHV0M2BTmd4gP1rPs,387
15
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=X3WX6tkqWl2H59fCJCNc3NIEkP4GoXImQLyCmvUlrMQ,77172
20
+ squad/api/rest.py,sha256=ZtbK0c1BLPPnsX79XlKFVYONM_VJ0vacWZ2JsdCd4l0,77342
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
@@ -26,13 +26,13 @@ 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
28
  squad/ci/models.py,sha256=Fm-4b3SDgMh9HXzqjOd4iZDRMJ1D9AnZ2cg7i2OR248,16018
29
- squad/ci/tasks.py,sha256=xoiOyh0HKLiKsAnQbolMRq4E9RcvP4xFgR0S9d_bgm4,3782
29
+ squad/ci/tasks.py,sha256=P0NYjLuyUViTpO1jZMuRVREbFDCccrMCZDw5E4pt928,3882
30
30
  squad/ci/utils.py,sha256=38zHpw8xkZDSFlkG-2BwSK6AkcddK9OkN9LXuQ3SHR0,97
31
31
  squad/ci/backend/__init__.py,sha256=yhpotXT9F4IdAOXvGQ3-17eOHAFwoaqf9SnMX17ab30,534
32
32
  squad/ci/backend/fake.py,sha256=9sPKndsGd5GDNPp35v-zfJWXZCbge-yXH3RBQGgTlPk,2340
33
- squad/ci/backend/lava.py,sha256=EXwEksjdOi_ZrUoMkBTyxVjqVOnJvEFNg_LWqUKaIgA,33607
33
+ squad/ci/backend/lava.py,sha256=E4QE0XtAiqArzzx3YSv7_2qYUBs4aSw8JOz0AV0z9W8,33877
34
34
  squad/ci/backend/null.py,sha256=0CVylWELIZw3JyzCROB4XXAjgQUi15YjQz5caRfTNBo,5434
35
- squad/ci/backend/tuxsuite.py,sha256=TzlWlhtITU53zDl7PJqk3V7LZ8m8LZ-aeURre5MSE5Q,17644
35
+ squad/ci/backend/tuxsuite.py,sha256=-A4p5HpUWnIC-61os0vdJOfAGoO81szoLkSgzyaUt6c,17901
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
@@ -76,17 +76,17 @@ squad/ci/templatetags/filter_jobs.py,sha256=IkWjfSJSeImWlpHk2Tz_aiqalJvprStl5h2J
76
76
  squad/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
77
  squad/core/admin.py,sha256=tFyRu_rhHN-ABJkEApaT4YtRYa4qxNe-8jou2H3Q0P4,7897
78
78
  squad/core/apps.py,sha256=Bl-4Yg0joKjygdifQG0ROIz4m5bHiPqytQ3G82uyzWc,143
79
- squad/core/callback.py,sha256=QhMf3ILkR2HAnqv1B2OW1pQEhrrIp4xRA9HhD6ywe1A,3066
79
+ squad/core/callback.py,sha256=tzj5PFQFiambicGikUg4yjYJ9WW6hDbO2e1jRCgAhVQ,3282
80
80
  squad/core/comparison.py,sha256=LR3-Unv0CTmakFCDzF_h8fm2peTJzkv79mQWNau1iwI,24429
81
81
  squad/core/data.py,sha256=2zw56v7iYRTUc7wlhuUNgwIIMmK2w84hi-amR9J7EPU,2236
82
82
  squad/core/failures.py,sha256=X6lJVghM2fOrd-RfuHeLlezW2pt7owDZ8eX-Kn_Qrt0,918
83
- squad/core/history.py,sha256=APIgJ1fXAGyxoNgxVMn02kJzXhLR1x2SG4UyCcTyUEQ,3467
84
- squad/core/models.py,sha256=DEkEs72gqX32237FoY-q8GN1DZ5cBRbegtLVgSlprGY,60508
83
+ squad/core/history.py,sha256=QRSIoDOw6R6vUWMtsPMknsHGM7FaCAeuCYqASCayHTk,3541
84
+ squad/core/models.py,sha256=jAQpsCo4uNPF2f93LI-_Wfpu5TjUhHFf6LfwXA8grU0,60859
85
85
  squad/core/notification.py,sha256=rOpO6F63w7_5l9gQgWBBEk-MFBjp7x_hVzoVIVyDze0,10030
86
86
  squad/core/plugins.py,sha256=FLgyoXXKnPBYEf2MgHup9M017rHuADHivLhgzmx_cJE,6354
87
87
  squad/core/queries.py,sha256=78fhIJZWXIlDryewYAt96beK1VJad66Ufu8cg3dHh4w,7698
88
88
  squad/core/statistics.py,sha256=xyTHuhdBjcJ4AozZESjTzSD3dBmmCDgLpbg5XpeyO_M,1056
89
- squad/core/utils.py,sha256=L6c-suSBbNFBVEZF7GF8DcjD5lmXZLy7QO0T_2j9LCk,4893
89
+ squad/core/utils.py,sha256=jinGlLEnr8nL84OzBvm0VFGt6EzWWR0r4dOabDrbXfM,4908
90
90
  squad/core/locale/django.pot,sha256=XycSJyEaEpozGBS9zu7QTNQbffZC0D9eSJ-AwXaVZx4,2282
91
91
  squad/core/locale/es_MX/LC_MESSAGES/django.po,sha256=bwvTWHK2KOT6zFqbIYh61_xYqRnMaQECZsMsOvNdMNw,3071
92
92
  squad/core/locale/pl/LC_MESSAGES/django.po,sha256=mI-Vo8OKWCcx4PrsoB6GiPY3lYU55tSqh0sO6fUeK2Y,3111
@@ -296,7 +296,7 @@ squad/frontend/apps.py,sha256=lKMd_HrIna5OZrfeWXndcGoIDR2KFmBFnMoGHtCGE4E,151
296
296
  squad/frontend/badges.py,sha256=rEgjkJQKZQT1mL9j9s47okTQO-J55eU8mDNHShijovY,5878
297
297
  squad/frontend/build_settings.py,sha256=_Hqw5npczuU01Zi6FGAiSbrtMMzK9eAXv-cX5U5btto,909
298
298
  squad/frontend/ci.py,sha256=lfglUArCj5iYRLZgC6mDgEN_k-dDqfCezXW3j2Fn_Uc,2244
299
- squad/frontend/comparison.py,sha256=tZQOcXOOTU787VbZ2ueuXpWGUjiFSeq-O7fepSM0g-I,4547
299
+ squad/frontend/comparison.py,sha256=Oy3Cffphy5qPsEGVAzICkCszb9JqHwaj-0RNMNxISLA,4721
300
300
  squad/frontend/extract.py,sha256=p88JGuBvaC4AMDkJi7lqzbj5ZGh6h2LSlV7tcXbmxDc,8491
301
301
  squad/frontend/forms.py,sha256=StPdrHsFsEoBKEOF6bBampLXbVXrZcEDkbuI4II1dCA,753
302
302
  squad/frontend/group_settings.py,sha256=mV0kJEfRo41AEbOZMxWXY1MpYNqSgWVqac0dUdwkGyk,6232
@@ -304,7 +304,7 @@ squad/frontend/metrics.py,sha256=nGrfFHLG6g_DUYVJCIDlFLvLWhMrqJxX1Z0cckPBJlg,114
304
304
  squad/frontend/project_settings.py,sha256=TtWz8h8Goeb3pccLy9jLUibeHqyqkdK8phL7_Vh_d0I,5045
305
305
  squad/frontend/queries.py,sha256=NxQF2woAf9A4Wk_ozHzZXOGmr2as-j7hqfvmsfJ-ojc,967
306
306
  squad/frontend/setup.py,sha256=NF9VunY1HJGB2HsHJss-go7EGmqr__JASddxiBCvmeQ,169
307
- squad/frontend/tests.py,sha256=q64Z6DyS6TiJTCzF6SXw4wZfvXR8c0A4t-f0ib1jJ0w,8713
307
+ squad/frontend/tests.py,sha256=PidrjaToK_Cks0s9Mc4i3Vh4UXOWoXTZlpnxQ2wWjHY,8740
308
308
  squad/frontend/urls.py,sha256=biWauxwXR5j9kOfrSUqkv1Iqz-elB2aNViS9_UFoLzQ,4882
309
309
  squad/frontend/user_settings.py,sha256=U_i59iuylg98uH98K4ezPa2NY56idslBhn7MS6FguHQ,4976
310
310
  squad/frontend/utils.py,sha256=DeH58CJUI1dovpQrj3a-DcxNzM0cxsnBDOF0mrC4Qws,1364
@@ -397,7 +397,7 @@ squad/frontend/templates/squad/testjob.jinja2,sha256=hQLavgkYJ3qAKJMG7cHnmJGC1jd
397
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
- squad/frontend/templates/squad/tests.jinja2,sha256=2AaEoCHJiCzXu_36XOq0ihiGqxh_2U2w88dheBlIwy8,4970
400
+ squad/frontend/templates/squad/tests.jinja2,sha256=8JvKe8GwLMGvoTSkofbl6aT-QBKDodMYN7RfKTzWF6U,4970
401
401
  squad/frontend/templates/squad/group_settings/advanced.jinja2,sha256=TbvNpZHK7fH3zx4Z_zwdmuhr8nev-jK8DhZ7_qQ7Osg,373
402
402
  squad/frontend/templates/squad/group_settings/base.jinja2,sha256=Mywqt3uLMNT7NyaUXiG4nDvdJULLuVX9sb6vYkgR1nQ,1437
403
403
  squad/frontend/templates/squad/group_settings/delete.jinja2,sha256=hO4mnNSph2D3qcAPUbffNgEdb-GsouSGxDRjcJ7NN8A,669
@@ -425,15 +425,15 @@ squad/plugins/__init__.py,sha256=9BSzy2jFIoDpWlhD7odPPrLdW4CC3btBhdFCvB651dM,152
425
425
  squad/plugins/example.py,sha256=BKpwd315lHRIuNXJPteibpwfnI6C5eXYHYdFYBtVmsI,89
426
426
  squad/plugins/gerrit.py,sha256=CqO2KnFQzu9utr_TQ-sGr1wg3ln0B-bS2-c0_i8T5-c,7009
427
427
  squad/plugins/github.py,sha256=pdtLZw_7xNuzkaFvY_zWi0f2rsMlalXjKm7sz0eADz4,2429
428
- squad/plugins/linux_log_parser.py,sha256=Ym0OBo6EurU0E_inPlf4-LwDryCtnazrTX7MaEZHRA0,4939
428
+ squad/plugins/linux_log_parser.py,sha256=8GgIM4skM06uZX1d-15nZ0D4lxg5jOp9XYRvMtUtjA0,7195
429
429
  squad/run/__init__.py,sha256=ssE8GPAGFiK6V0WpZYowav6Zqsd63dfDMMYasNa1sQg,1410
430
430
  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.87.dist-info/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
435
- squad-1.87.dist-info/METADATA,sha256=h0QpQouYSIQVhf2bANIYw5E4oREwaZAJvVm81i5hn-Q,1281
436
- squad-1.87.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
437
- squad-1.87.dist-info/entry_points.txt,sha256=apCDQydHZtvqV334ql6NhTJUAJeZRdtAm0TVcbbAi5Q,194
438
- squad-1.87.dist-info/top_level.txt,sha256=_x9uqE1XppiiytmVTl_qNgpnXus6Gsef69HqfliE7WI,6
439
- squad-1.87.dist-info/RECORD,,
434
+ squad-1.89.dist-info/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
435
+ squad-1.89.dist-info/METADATA,sha256=Kb687CzcwB57kqLaoR1vJ9H6ESKXgDx5UToU4yOcZFg,1281
436
+ squad-1.89.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
437
+ squad-1.89.dist-info/entry_points.txt,sha256=apCDQydHZtvqV334ql6NhTJUAJeZRdtAm0TVcbbAi5Q,194
438
+ squad-1.89.dist-info/top_level.txt,sha256=_x9uqE1XppiiytmVTl_qNgpnXus6Gsef69HqfliE7WI,6
439
+ squad-1.89.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes