squad 1.87__py3-none-any.whl → 1.89__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.
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