import urllib import csv from django.http import HttpResponse from datetime import date, datetime from django.http import Http404 from django.shortcuts import get_object_or_404 from django.views.generic import ListView, DetailView from django.core.urlresolvers import resolve from layerindex.models import Recipe from rrs.models import Release, Milestone, Maintainer, RecipeMaintainerHistory, \ RecipeMaintainer, RecipeUpstreamHistory, RecipeUpstream, \ RecipeDistro, RecipeUpgrade, Raw def _check_url_params(upstream_status, maintainer_name): get_object_or_404(Maintainer, name=maintainer_name) found = 0 for us in RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES_DICT.keys(): if us == 'D': # Downgrade is displayed as Unknown continue if RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES_DICT[us] == upstream_status: found = 1 break if found == 0: raise Http404 def _get_layer_branch_url(branch, layer_name): return ("http://layers.openembedded.org/layerindex/branch/%s/layer/%s/"\ % (branch, layer_name)) def _get_milestone_statistics(milestone, maintainer_name=None): milestone_statistics = {} recipe_upstream_history = RecipeUpstreamHistory.get_last_by_date_range( milestone.start_date, milestone.end_date ) if maintainer_name is None: milestone_statistics['all'] = Recipe.objects.all().count() milestone_statistics['up_to_date'] = \ RecipeUpstream.get_recipes_up_to_date(recipe_upstream_history).count() milestone_statistics['not_updated'] = \ RecipeUpstream.get_recipes_not_updated(recipe_upstream_history).count() milestone_statistics['cant_be_updated'] = \ RecipeUpstream.get_recipes_cant_be_updated(recipe_upstream_history).count() milestone_statistics['unknown'] = \ RecipeUpstream.get_recipes_unknown(recipe_upstream_history).count() else: recipe_maintainer_history = Raw.get_remahi_by_end_date( milestone.end_date) recipe_maintainer_all = Raw.get_re_by_mantainer_and_date( maintainer_name, recipe_maintainer_history[0]) milestone_statistics['all'] = len(recipe_maintainer_all) if recipe_upstream_history: recipe_upstream_all = Raw.get_reup_by_recipes_and_date( recipe_maintainer_all, recipe_upstream_history.id) else: recipe_upstream_all = Raw.get_reup_by_recipes_and_date( recipe_maintainer_all) milestone_statistics['up_to_date'] = 0 milestone_statistics['not_updated'] = 0 milestone_statistics['cant_be_updated'] = 0 milestone_statistics['unknown'] = 0 for ru in recipe_upstream_all: if ru['status'] == 'Y': milestone_statistics['up_to_date'] += 1 elif ru['status'] == 'N': if ru['no_update_reason'] == '': milestone_statistics['not_updated'] += 1 else: milestone_statistics['cant_be_updated'] += 1 else: milestone_statistics['unknown'] += 1 if milestone_statistics['all'] == 0: milestone_statistics['percentage'] = 0 else: milestone_statistics['percentage'] = "%.0f" % \ ((float(milestone_statistics['up_to_date']) / float(milestone_statistics['all'])) * 100) return milestone_statistics class RecipeList(): pk = None name = None version = None summary = None upstream_status = None upstream_version = None outdated = None maintainer_name = None no_update_reason = None def __init__(self, pk, name, summary): self.pk = pk self.name = name self.summary = summary def _get_recipe_list(milestone): recipe_maintainer_history = Raw.get_remahi_by_end_date( milestone.end_date) recipe_upstream_history = RecipeUpstreamHistory.get_last_by_date_range( milestone.start_date, milestone.end_date ) recipe_list = [] recipes_ids = [] recipe_upstream_dict_all = {} recipe_last_updated_dict_all = {} maintainers_dict_all = {} current_date = date.today() # If the is the curent milestone take the data recipes table # otherwise take it from recipe upgrade if current_date >= milestone.start_date and \ current_date <= milestone.end_date: recipes = Raw.get_re_all() else: recipes = Raw.get_reupg_by_date(milestone.end_date) for i,re in enumerate(recipes): if re.has_key('pv'): recipes[i]['version'] = re['pv'] recipes_ids.append(re['id']) if recipe_upstream_history: recipe_upstream_all = Raw.get_reup_by_recipes_and_date( recipes_ids, recipe_upstream_history.id) recipe_last_updated = Raw.get_reup_by_last_updated( milestone.end_date) maintainers_all = Raw.get_ma_by_recipes_and_date( recipes_ids, recipe_maintainer_history[0]) for reup in recipe_upstream_all: recipe_upstream_dict_all[reup['recipe_id']] = reup for rela in recipe_last_updated: recipe_last_updated_dict_all[rela['recipe_id']] = rela for ma in maintainers_all: maintainers_dict_all[ma['recipe_id']] = ma['name'] else: recipe_upstream_all = None for recipe in recipes: upstream_version = '' upstream_status = '' no_update_reason = '' outdated = '' if recipe_upstream_history: recipe_upstream = recipe_upstream_dict_all.get(recipe['id']) if not recipe_upstream: recipe_add = Recipe.objects.filter(id = recipe['id'])[0] recipe_upstream_add = RecipeUpstream() recipe_upstream_add.history = recipe_upstream_history recipe_upstream_add.recipe = recipe_add recipe_upstream_add.version = '' recipe_upstream_add.type = 'M' # Manual recipe_upstream_add.status = 'U' # Unknown recipe_upstream_add.no_update_reason = '' recipe_upstream_add.date = recipe_upstream_history.end_date recipe_upstream_add.save() recipe_upstream = {'version': '', 'status': 'U', 'type': 'M', 'no_update_reason': ''} if recipe_upstream['status'] == 'N' and recipe_upstream['no_update_reason']: recipe_upstream['status'] = 'C' upstream_status = \ RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES_DICT[ recipe_upstream['status']] if upstream_status == 'Downgrade': upstream_status = 'Unknown' # Downgrade is displayed as Unknown upstream_version = recipe_upstream['version'] no_update_reason = recipe_upstream['no_update_reason'] #Get how long the recipe hasn't been updated if recipe_upstream['status'] != 'Y': recipe_last_updated = \ recipe_last_updated_dict_all.get(recipe['id']) if recipe_last_updated: recipe_date = recipe_last_updated['date'] outdated = (current_date - recipe_date.date()).days else: outdated = 'Unknown' else: outdated = 'Up-to-date' maintainer_name = maintainers_dict_all.get(recipe['id'], '') recipe_list_item = RecipeList(recipe['id'], recipe['pn'], recipe['summary']) recipe_list_item.version = recipe['version'] recipe_list_item.upstream_status = upstream_status recipe_list_item.upstream_version = upstream_version recipe_list_item.outdated = outdated recipe_list_item.maintainer_name = maintainer_name recipe_list_item.no_update_reason = no_update_reason recipe_list.append(recipe_list_item) return recipe_list class RecipeListView(ListView): context_object_name = 'recipe_list' def get_queryset(self): self.release_name = self.kwargs['release_name'] release = get_object_or_404(Release, name=self.release_name) self.milestone_name = self.kwargs['milestone_name'] milestone = get_object_or_404(Milestone, release = release, name=self.milestone_name) if 'upstream_status' in self.request.GET.keys(): self.upstream_status = self.request.GET['upstream_status'] else: self.upstream_status = 'All' if 'maintainer_name' in self.request.GET.keys(): self.maintainer_name = self.request.GET['maintainer_name'] else: self.maintainer_name = 'All' _check_url_params(self.upstream_status, self.maintainer_name) self.milestone_statistics = _get_milestone_statistics(milestone) self.recipe_maintainer_history = RecipeMaintainerHistory.get_by_end_date( milestone.end_date) recipe_list = _get_recipe_list(milestone) self.recipe_list_count = len(recipe_list) return recipe_list def get_context_data(self, **kwargs): context = super(RecipeListView, self).get_context_data(**kwargs) context['this_url_name'] = resolve(self.request.path_info).url_name context['release_name'] = self.release_name context['all_releases'] = Release.objects.filter().order_by('-end_date') context['milestone_name'] = self.milestone_name context['all_milestones'] = Milestone.get_by_release_name(self.release_name) context['recipes_percentage'] = self.milestone_statistics['percentage'] context['recipes_up_to_date'] = self.milestone_statistics['up_to_date'] context['recipes_not_updated'] = self.milestone_statistics['not_updated'] context['recipes_cant_be_updated'] = self.milestone_statistics['cant_be_updated'] context['recipes_unknown'] = self.milestone_statistics['unknown'] context['recipe_list_count'] = self.recipe_list_count context['upstream_status'] = self.upstream_status ruch = RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES_DICT context['upstream_status_set_choices'] = [ruch['A']] context['upstream_status_choices'] = [ruch['N'], ruch['C'], ruch['Y'], ruch['U']] context['maintainer_name'] = self.maintainer_name context['set_maintainers'] = ['All', 'No maintainer'] all_maintainers = [] for rm in RecipeMaintainer.objects.filter(history = self.recipe_maintainer_history).values( 'maintainer__name').distinct().order_by('maintainer__name'): if rm['maintainer__name'] in context['set_maintainers']: continue all_maintainers.append(rm['maintainer__name']) context['all_maintainers'] = all_maintainers return context def recipes_report(request, release_name, milestone_name): release = get_object_or_404(Release, name=release_name) milestone = get_object_or_404(Milestone, release = release, name=milestone_name) recipe_list = _get_recipe_list(milestone) response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = 'attachment; filename="%s.csv"' % (milestone_name) writer = csv.writer(response) writer.writerow(['Upstream status', 'Name', 'Version', 'Upstream version', 'Maintainer', 'Summary']) for r in recipe_list: writer.writerow([r.upstream_status, r.name, r.version, r.upstream_version, r.maintainer_name.encode('utf-8'), r.summary]) return response class RecipeUpgradeDetail(): title = None version = None release_name = None milestone_name = None date = None maintainer_name = None is_recipe_maintainer = None commit = None commit_url = None def __init__(self, title, version, release_name, milestone_name, date, maintainer_name, is_recipe_maintainer, commit, commit_url): self.title = title self.version = version self.release_name = release_name self.milestone_name = milestone_name self.date = date self.maintainer_name = maintainer_name self.is_recipe_maintainer = is_recipe_maintainer self.commit = commit self.commit_url = commit_url def _get_recipe_upgrade_detail(recipe_upgrade): release_name = '' milestone_name = '' recipe_maintainer_history = None release = Release.get_by_date(recipe_upgrade.commit_date) if release: release_name = release.name milestone = Milestone.get_by_release_and_date(release, recipe_upgrade.commit_date) if milestone: milestone_name = milestone.name recipe_maintainer_history = RecipeMaintainerHistory.get_by_end_date( milestone.end_date) is_recipe_maintainer = False maintainer_name = '' if not recipe_upgrade.maintainer is None: maintainer_name = recipe_upgrade.maintainer.name if not recipe_maintainer_history is None and \ RecipeMaintainer.objects.filter(maintainer__name = maintainer_name, history = recipe_maintainer_history) \ .count() > 0: is_recipe_maintainer = True commit = recipe_upgrade.sha1[:10] commit_url = recipe_upgrade.recipe.layerbranch.layer.vcs_web_url + \ '/commit/?id=' + recipe_upgrade.sha1 rud = RecipeUpgradeDetail(recipe_upgrade.title, recipe_upgrade.version, \ release_name, milestone_name, recipe_upgrade.commit_date, \ maintainer_name, is_recipe_maintainer, commit, commit_url) return rud class RecipeDetailView(DetailView): model = Recipe def get_context_data(self, **kwargs): context = super(RecipeDetailView, self).get_context_data(**kwargs) recipe = self.get_object() if not recipe: raise django.http.Http404 release = Release.get_current() context['release_name'] = release.name milestone = Milestone.get_current(release) context['milestone_name'] = milestone.name context['upstream_status'] = '' context['upstream_version'] = '' context['upstream_no_update_reason'] = '' recipe_upstream_history = RecipeUpstreamHistory.get_last_by_date_range( milestone.start_date, milestone.end_date ) if recipe_upstream_history: recipe_upstream = RecipeUpstream.get_by_recipe_and_history( recipe, recipe_upstream_history) if recipe_upstream: if recipe_upstream.status == 'N' and recipe_upstream.no_update_reason: recipe_upstream.status = 'C' elif recipe_upstream.status == 'D': recipe_upstream.status = 'U' context['upstream_status'] = \ RecipeUpstream.RECIPE_UPSTREAM_STATUS_CHOICES_DICT[recipe_upstream.status] context['upstream_version'] = recipe_upstream.version context['upstream_no_update_reason'] = recipe_upstream.no_update_reason self.recipe_maintainer_history = RecipeMaintainerHistory.get_last() recipe_maintainer = RecipeMaintainer.objects.filter(recipe = recipe, history = self.recipe_maintainer_history) if recipe_maintainer: maintainer = recipe_maintainer[0].maintainer context['maintainer_name'] = maintainer.name else: context['maintainer_name'] = 'No maintainer' context['recipe_upgrade_details'] = [] for ru in RecipeUpgrade.objects.filter(recipe = recipe).order_by('-commit_date'): context['recipe_upgrade_details'].append(_get_recipe_upgrade_detail(ru)) context['recipe_upgrade_detail_count'] = len(context['recipe_upgrade_details']) context['recipe_layer_branch_url'] = _get_layer_branch_url( recipe.layerbranch.branch.name, recipe.layerbranch.layer.name) context['recipe_provides'] = [] for p in recipe.provides.split(): context['recipe_provides'].append(p) context['recipe_depends'] = [] for d in recipe.depends.split(): context['recipe_depends'].append(d) context['recipe_distros'] = RecipeDistro.get_distros_by_recipe(recipe) return context class MaintainerList(): name = None recipes_all = 0 recipes_up_to_date = '0' recipes_not_updated = '0' recipes_cant_be_updated = '0' recipes_unknown = '0' percentage_done = '0.00' interval_statistics = None def __init__(self, name): self.name = name class MaintainerListView(ListView): context_object_name = 'maintainer_list' def get_queryset(self): maintainer_list = [] self.maintainer_count = 0 self.release_name = self.kwargs['release_name'] release = get_object_or_404(Release, name=self.release_name) self.milestone_name = self.kwargs['milestone_name'] milestone = get_object_or_404(Milestone, release = release, name=self.milestone_name) if "All" in milestone.name: intervals = milestone.get_milestone_intervals(release) interval_type = 'Milestone' else: intervals = milestone.get_week_intervals() interval_type = 'Week' self.milestone_statistics = _get_milestone_statistics(milestone) recipe_maintainer_history = RecipeMaintainerHistory.get_by_end_date( milestone.end_date) if recipe_maintainer_history: for rm in RecipeMaintainer.objects.filter(history = recipe_maintainer_history).values( 'maintainer__name').distinct().order_by('maintainer__name'): maintainer_list.append(MaintainerList(rm['maintainer__name'])) self.maintainer_count = len(maintainer_list) self.intervals = sorted(intervals.keys()) current_date = date.today() for ml in maintainer_list: milestone_statistics = _get_milestone_statistics(milestone, ml.name) ml.recipes_all = milestone_statistics['all'] ml.recipes_up_to_date = ('' if milestone_statistics['up_to_date'] == 0 else milestone_statistics['up_to_date']) ml.recipes_not_updated = ('' if milestone_statistics['not_updated'] == 0 else milestone_statistics['not_updated']) ml.recipes_cant_be_updated = ('' if milestone_statistics['cant_be_updated'] == 0 else milestone_statistics['cant_be_updated']) ml.recipes_unknown = ('' if milestone_statistics['unknown'] == 0 else milestone_statistics['unknown']) ml.percentage_done = milestone_statistics['percentage'] + '%' ml.interval_statistics = [] self.current_interval = -1 for idx, i in enumerate(sorted(intervals.keys())): start_date = intervals[i]['start_date'] end_date = intervals[i]['end_date'] if current_date >= start_date and current_date <= end_date: self.current_interval = idx number = RecipeUpgrade.objects.filter(maintainer__name = ml.name, commit_date__gte = start_date, commit_date__lte = end_date).count() ml.interval_statistics.append('' if number == 0 else number) # To add Wk prefix after get statics to avoid sorting problems if interval_type == 'Week': self.intervals = ['Wk' + str(i) for i in self.intervals] return maintainer_list def get_context_data(self, **kwargs): context = super(MaintainerListView, self).get_context_data(**kwargs) context['this_url_name'] = resolve(self.request.path_info).url_name context['release_name'] = self.release_name context['all_releases'] = Release.objects.filter().order_by('-end_date') context['milestone_name'] = self.milestone_name context['all_milestones'] = Milestone.get_by_release_name(self.release_name) context['recipes_percentage'] = self.milestone_statistics['percentage'] context['recipes_up_to_date'] = self.milestone_statistics['up_to_date'] context['recipes_not_updated'] = self.milestone_statistics['not_updated'] context['recipes_cant_be_updated'] = self.milestone_statistics['cant_be_updated'] context['recipes_unknown'] = self.milestone_statistics['unknown'] context['maintainer_count'] = self.maintainer_count context['intervals'] = self.intervals context['interval_range'] = range(len(self.intervals)) if hasattr(self, 'current_interval'): context['current_interval'] = self.current_interval return context