19
19
from collections import defaultdict, OrderedDict
25
24
from urllib.request import urlopen
29
27
from jinja2 import Environment, FileSystemLoader
34
31
loader=FileSystemLoader(os.path.dirname(os.path.abspath(__file__)) + '/templates'),
126
123
def get_subscribers_json(packages, subscribers_json):
127
124
if subscribers_json is None:
128
j = urlopen("https://ubuntu-archive-team.ubuntu.com/package-team-mapping.json")
125
j = urlopen("http://people.canonical.com/~ubuntu-archive/package-team-mapping.json")
130
127
j = open(subscribers_json, 'rb')
191
188
waiting = attr.ib(default=None) # [(source_package_name, arches)]
192
189
data = attr.ib(default=None) # data for package_in_proposed
193
190
unsatdepends = attr.ib(default=None) # [string]
194
unsatbuilddep = attr.ib(default=None) # [string]
195
brokenbin = attr.ib(default=None) # [string]
196
componentmismatch = attr.ib(default=None) # [string]
198
192
_age = attr.ib(default=None)
244
235
print("fetching yaml")
245
236
if args.excuses_yaml:
246
if args.excuses_yaml.endswith('.xz'):
247
yaml_text = lzma.open(args.excuses_yaml)
249
yaml_text = open(args.excuses_yaml)
237
yaml_text = open(args.excuses_yaml).read()
252
yaml_text = lzma.open(urlopen("https://ubuntu-archive-team.ubuntu.com/proposed-migration/update_excuses.yaml.xz"))
253
except urllib.error.HTTPError as e:
254
print("Reading fallback yaml (%s)" % e)
255
yaml_text = urlopen("https://ubuntu-archive-team.ubuntu.com/proposed-migration/update_excuses.yaml")
239
yaml_text = urlopen("https://people.canonical.com/~ubuntu-archive/proposed-migration/update_excuses.yaml").read()
256
240
print("parsing yaml")
257
241
# The CSafeLoader is ten times faster than the regular one
258
242
excuses = yaml.load(yaml_text, Loader=yaml.CSafeLoader)
264
248
# Missing component means main
265
249
if item.get('component', 'main') not in components:
267
prob = Problem(kind='package-in-proposed', data=defaultdict(dict, item), package_in_proposed=source_package_name)
251
prob = Problem(kind='package-in-proposed', data=item, package_in_proposed=source_package_name)
268
252
in_proposed_packages[source_package_name] = prob
269
253
prob.regressions = []
270
254
prob.waiting = []
271
prob.componentmismatch = []
272
# The verdict entries are not items to list on the report
273
for policy in ['autopkgtest', 'update-excuse', 'block-bugs']:
275
del item['policy_info'][policy]['verdict']
278
255
if 'autopkgtest' in item['reason']:
279
256
for package, results in sorted(item['policy_info']['autopkgtest'].items()):
292
269
prob.regressions.append(regr)
294
271
prob.waiting.append((package + ": " + ", ".join(wait_arches)))
295
if 'depends' in item['reason']:
296
for l in item['excuses']:
297
if 'cannot depend on' in l:
298
prob.componentmismatch.append(l)
299
272
if 'dependencies' in item and 'unsatisfiable-dependencies' in item['dependencies']:
300
273
unsatd = defaultdict(list)
301
274
for arch, packages in item['dependencies']['unsatisfiable-dependencies'].items():
302
275
for p in packages:
303
276
unsatd[p].append(arch)
304
277
prob.unsatdepends = ['{}: {}'.format(p, ', '.join(sorted(arches))) for p, arches in sorted(unsatd.items())]
305
if 'policy_info' in item:
306
if 'build-depends' in item['policy_info'] and 'unsatisfiable-arch-build-depends' in item['policy_info']['build-depends']:
307
unsatdbd = defaultdict(list)
308
for arch, packages in item['policy_info']['build-depends']['unsatisfiable-arch-build-depends'].items():
310
unsatdbd[p].append(arch)
311
prob.unsatbuilddep = ['{}: {}'.format(p, ', '.join(sorted(arches))) for p, arches in sorted(unsatdbd.items())]
312
if 'implicit-deps' in item['policy_info']['implicit-deps']:
313
prob.brokenbin = item['policy_info']['implicit-deps']['implicit-deps']['broken-binaries']
315
279
package_to_problems = defaultdict(list)
317
281
for problem in in_proposed_packages.values():
318
# nautilus/riscv64 -> nautilus
319
pkg = problem.package_in_proposed.split('/')[0]
320
package_to_problems[pkg].append(problem)
282
package_to_problems[problem.package_in_proposed].append(problem)
321
283
for regression in problem.regressions:
322
284
if regression.blocking not in in_proposed_packages:
345
307
subscribers = get_subscribers_json(set(package_to_problems), args.subscribers_json)
346
308
for p in set(package_to_problems):
347
pkg = p.split('/')[0]
348
if pkg not in subscribers:
309
if p not in subscribers:
349
310
subscribers[p] = ['unknown']
351
312
all_teams = set()
369
330
all_teams=all_teams,
370
331
team_to_problems=team_to_problems,
371
332
team_to_attn_count=team_to_attn_count,
372
now=excuses["generated-date"].strftime("%Y.%m.%d %H:%M:%S") + ' ' + time.localtime().tm_zone))
333
now=excuses["generated-date"].strftime("%Y.%m.%d %H:%M:%S")))
373
334
if args.yaml_output:
374
335
team_to_problem_data = {}
375
336
for t, ps in team_to_problems.items():