[Toaster] [-M] toaster: Rework displaying package dependencies across Toaster

Ed Bartosh ed.bartosh at linux.intel.com
Tue Jun 7 01:52:16 PDT 2016


sorry, wrong patch. please, ignore.

On Tue, Jun 07, 2016 at 11:47:22AM +0300, Ed Bartosh wrote:
> From: Michael Wood <michael.g.wood at intel.com>
> 
> After porting the build table to a unified mechanism for showing
> dependencies in tables it highlighted that the dependencies selected to
> be shown were un-filtered. i.e. all dependencies from all contexts were
> shown. The context for a package's dependencies is based on the target
> that they were installed onto, or if not installed then a "None" target.
> 
> Depending on where the template for the dependencies are show we need to
> switch this target which is why a filter and utility function on the
> model is added.
> 
> Additionally to use the same templates in the build analysis we also
> need to optionally add links to the build data for the packages being
> displayed as dependencies.
> 
> Customising a Custom image recipes may or may not have a target
> depending on whether they have been built or not, if not we do a best
> effort at getting the dependencies by using the last known target on
> that package to get the dependency information.
> 
> [YOCTO #9676]
> 
> Signed-off-by: Michael Wood <michael.g.wood at intel.com>
> Signed-off-by: Ed Bartosh <ed.bartosh at linux.intel.com>
> ---
>  bitbake/lib/toaster/orm/models.py                  | 61 ++++++++++++++++++----
>  bitbake/lib/toaster/toastergui/buildtables.py      | 15 +++++-
>  bitbake/lib/toaster/toastergui/tables.py           | 15 +++++-
>  .../snippets/pkg_dependencies_popover.html         | 44 ++++++++++++----
>  .../snippets/pkg_revdependencies_popover.html      | 46 ++++++++++++----
>  .../toaster/toastergui/templatetags/projecttags.py |  8 +++
>  bitbake/lib/toaster/toastergui/views.py            |  4 +-
>  7 files changed, 157 insertions(+), 36 deletions(-)
> 
> diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
> index 25bc1db..caad2af 100644
> --- a/bitbake/lib/toaster/orm/models.py
> +++ b/bitbake/lib/toaster/orm/models.py
> @@ -862,31 +862,70 @@ class CustomImagePackage(Package):
>                                              related_name='appends_set')
>  
>  
> -
>  class Package_DependencyManager(models.Manager):
>      use_for_related_fields = True
> +    TARGET_LATEST = "use-latest-target-for-target"
>  
>      def get_queryset(self):
>          return super(Package_DependencyManager, self).get_queryset().exclude(package_id = F('depends_on__id'))
>  
> -    def get_total_source_deps_size(self):
> -        """ Returns the total file size of all the packages that depend on
> -        thispackage.
> -        """
> -        return self.all().aggregate(Sum('depends_on__size'))
> +    def for_target_or_none(self, target):
> +        """ filter the dependencies to be displayed by the supplied target
> +        if no dependences are found for the target then try None as the target
> +        which will return the dependences calculated without the context of a
> +        target e.g. non image recipes.
>  
> -    def get_total_revdeps_size(self):
> -        """ Returns the total file size of all the packages that depend on
> -        this package.
> +        returns: { size, packages }
>          """
> -        return self.all().aggregate(Sum('package_id__size'))
> +        package_dependencies = self.all_depends().order_by('depends_on__name')
>  
> +        if target is self.TARGET_LATEST:
> +            installed_deps =\
> +                    package_dependencies.filter(~Q(target__target=None))
> +        else:
> +            installed_deps =\
> +                    package_dependencies.filter(Q(target__target=target))
> +
> +        packages_list = None
> +        total_size = 0
> +
> +        # If we have installed depdencies for this package and target then use
> +        # these to display
> +        if installed_deps.count() > 0:
> +            packages_list = installed_deps
> +            total_size = installed_deps.aggregate(
> +                Sum('depends_on__size'))['depends_on__size__sum']
> +        else:
> +            new_list = []
> +            package_names = []
> +
> +            # Find dependencies for the package that we know about even if
> +            # it's not installed on a target e.g. from a non-image recipe
> +            for p in package_dependencies.filter(Q(target=None)):
> +                if p.depends_on.name in package_names:
> +                    continue
> +                else:
> +                    package_names.append(p.depends_on.name)
> +                    new_list.append(p.pk)
> +                    # while we're here we may as well total up the size to
> +                    # avoid iterating again
> +                    total_size += p.depends_on.size
> +
> +            # We want to return a queryset here for consistency so pick the
> +            # deps from the new_list
> +            packages_list = package_dependencies.filter(Q(pk__in=new_list))
> +
> +        return {'packages': packages_list,
> +                'size': total_size}
>  
>      def all_depends(self):
> -        """ Returns just the depends packages and not any other dep_type """
> +        """ Returns just the depends packages and not any other dep_type
> +        Note that this is for any target
> +        """
>          return self.filter(Q(dep_type=Package_Dependency.TYPE_RDEPENDS) |
>                             Q(dep_type=Package_Dependency.TYPE_TRDEPENDS))
>  
> +
>  class Package_Dependency(models.Model):
>      TYPE_RDEPENDS = 0
>      TYPE_TRDEPENDS = 1
> diff --git a/bitbake/lib/toaster/toastergui/buildtables.py b/bitbake/lib/toaster/toastergui/buildtables.py
> index 17de369..e237e4e 100644
> --- a/bitbake/lib/toaster/toastergui/buildtables.py
> +++ b/bitbake/lib/toaster/toastergui/buildtables.py
> @@ -47,6 +47,7 @@ class BuiltPackagesTableBase(tables.PackagesTable):
>      def setup_queryset(self, *args, **kwargs):
>          build = Build.objects.get(pk=kwargs['build_id'])
>          self.static_context_extra['build'] = build
> +        self.static_context_extra['target_name'] = None
>          self.queryset = build.package_set.all().exclude(recipe=None)
>          self.queryset = self.queryset.order_by(self.default_orderby)
>  
> @@ -187,7 +188,15 @@ class InstalledPackagesTable(BuildTablesMixin, BuiltPackagesTableBase):
>          self.static_context_extra['build'] = build
>  
>          target = Target.objects.get(pk=kwargs['target_id'])
> +        # We send these separately because in the case of image details table
> +        # we don't have a target just the recipe name as the target
> +        self.static_context_extra['target_name'] = target.target
> +        self.static_context_extra['target_id'] = target.pk
> +
> +        self.static_context_extra['add_links'] = True
> +
>          self.queryset = self.make_package_list(target)
> +        self.queryset = self.queryset.order_by(self.default_orderby)
>  
>      def setup_columns(self, *args, **kwargs):
>          super(InstalledPackagesTable, self).setup_columns(**kwargs)
> @@ -195,11 +204,13 @@ class InstalledPackagesTable(BuildTablesMixin, BuiltPackagesTableBase):
>                          static_data_name="installed_size",
>                          static_data_template="{% load projecttags %}"
>                          "{{data.size|filtered_filesizeformat}}",
> -                        orderable=True)
> +                        orderable=True,
> +                        hidden=True)
>  
>          # Add the template to show installed name for installed packages
>          install_name_tmpl =\
> -            ('{{data.name}} '
> +            ('<a href="{% url "package_included_detail" extra.build.pk'
> +             ' extra.target_id data.pk %}">{{data.name}}</a>'
>               '{% if data.installed_name and data.installed_name !='
>               ' data.name %}'
>               '<span class="muted"> as {{data.installed_name}}</span>'
> diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
> index 902f62f..79673f5 100644
> --- a/bitbake/lib/toaster/toastergui/tables.py
> +++ b/bitbake/lib/toaster/toastergui/tables.py
> @@ -22,7 +22,7 @@
>  from toastergui.widgets import ToasterTable
>  from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
>  from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task
> -from orm.models import CustomImagePackage
> +from orm.models import CustomImagePackage, Package_DependencyManager
>  from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField
>  from django.conf.urls import url
>  from django.core.urlresolvers import reverse, resolve
> @@ -695,6 +695,7 @@ class PackagesTable(ToasterTable):
>  
>      def setup_queryset(self, *args, **kwargs):
>          recipe = Recipe.objects.get(pk=kwargs['recipe_id'])
> +        self.static_context_extra['target_name'] = recipe.name
>  
>          self.queryset = self.create_package_list(recipe, kwargs['pid'])
>          self.queryset = self.queryset.order_by('name')
> @@ -766,7 +767,19 @@ class SelectPackagesTable(PackagesTable):
>  
>          self.queryset = self.queryset.order_by('name')
>  
> +        # This target is the target used to work out which group of dependences
> +        # to display, if we've built the custom image we use it otherwise we
> +        # can use the based recipe instead
> +        if prj.build_set.filter(target__target=self.cust_recipe.name).count()\
> +           > 0:
> +            self.static_context_extra['target_name'] = self.cust_recipe.name
> +        else:
> +            self.static_context_extra['target_name'] =\
> +                    Package_DependencyManager.TARGET_LATEST
> +
>          self.static_context_extra['recipe_id'] = kwargs['custrecipeid']
> +
> +
>          self.static_context_extra['current_packages'] = \
>                  current_packages.values_list('pk', flat=True)
>  
> diff --git a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
> index 0a24e92..5be409c 100644
> --- a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
> +++ b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
> @@ -1,14 +1,38 @@
>  {# Popover that displays the dependences and sizes of a package 'data' used in the Packages table #}
> -{% with data.package_dependencies_source.all_depends.count as dep_count %}
>  {% load projecttags %}
> -{% if dep_count %}
> - <a data-content="<ul class='list-unstyled'>
> -   {% for dep in data.package_dependencies_source.all_depends %}
> -  <li>{{dep.depends_on.name}} {% if dep.depends_on.size > 0 %}({{dep.depends_on.size|filtered_filesizeformat}}){% endif %}</li>
> -    {% endfor %}
> -  </ul>" class="btn btn-default" title="
> -  <strong>{{data.name}}</strong> dependencies - <strong>{{data.package_dependencies_source.get_total_source_deps_size.depends_on__size__sum|filtered_filesizeformat}}</strong>">
> -    {{dep_count}}
> -</a>
> +
> +{% with package_deps=data.package_dependencies_source|for_target:extra.target_name %}
> +{% with count_package=package_deps.packages|length %}
> +
> +{% if count_package > 0 %}
> +  <a data-content='<ul class="unstyled">
> +  {% for dep in package_deps.packages %}
> +     <li>
> +      {% if extra.add_links %}
> +      <a href="{% url 'package_included_detail' extra.build.pk extra.target_id dep.depends_on.pk %}">
> +      {{dep.depends_on.name}}</a>
> +      {% else %}
> +        {{dep.depends_on.name}}
> +      {% endif %}
> +      {% if dep.depends_on.size > 0 %}
> +        ({{dep.depends_on.size|filtered_filesizeformat}})
> +      {% endif %}
> +     </li>
> +   {% endfor %}
> +   </ul>' class="btn btn-default" title='
> +   <strong>
> +     {% if extra.add_links %}
> +      <a href="{% url 'package_included_dependencies' extra.build.pk extra.target_id data.pk %}">
> +      {{data.name}}</a>
> +      {% else %}
> +      {{data.name}}
> +      {% endif %}
> +      </strong>
> +      dependencies -
> +      <strong>{{package_deps.size|filtered_filesizeformat}}</strong>'>
> +      {{count_package}}
> +  </a>
>  {% endif %}
> +
> +{% endwith %}
>  {% endwith %}
> diff --git a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
> index d470712..65c2b29 100644
> --- a/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
> +++ b/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
> @@ -1,14 +1,38 @@
> -{# Popover that displays the reverse dependencies and sizes of a package 'data' used in the Packages table #}
> -{% with data.package_dependencies_target.all_depends.count as dep_count %}
> +{# Popover that displays the reverse dependences and sizes of a package 'data' used in the Packages table #}
>  {% load projecttags %}
> -{% if dep_count %}
> - <a data-content="<ul class='list-unstyled'>
> -   {% for dep in data.package_dependencies_target.all_depends|dictsort:'package.name' %}
> -  <li>{{dep.package.name}} {% if dep.package.size > 0 %}({{dep.package.size|filtered_filesizeformat}}){% endif %}</li>
> -    {% endfor %}
> -  </ul>" class="btn btn-default" title="
> -  <strong>{{data.name}}</strong> reverse dependencies - <strong>{{data.package_dependencies_target.get_total_revdeps_size.package_id__size__sum|filtered_filesizeformat}}</strong>">
> -    {{dep_count}}
> -</a>
> +
> +{% with package_deps=data.package_dependencies_target|for_target:extra.target_name %}
> +{% with count_package=package_deps.packages|length %}
> +
> +{% if count_package > 0 %}
> +  <a data-content='<ul class="unstyled">
> +  {% for dep in package_deps.packages|dictsort:"package.name" %}
> +     <li>
> +      {% if extra.add_links %}
> +      <a href="{% url 'package_included_detail' extra.build.pk extra.target_id dep.package.pk %}">
> +      {{dep.package.name}}</a>
> +      {% else %}
> +      {{dep.package.name}}
> +      {% endif %}
> +      {% if dep.package.size > 0 %}
> +        ({{dep.package.size|filtered_filesizeformat}})
> +      {% endif %}
> +     </li>
> +   {% endfor %}
> +   </ul>' class="btn btn-default" title='
> +   <strong>
> +     {% if extra.add_links %}
> +      <a href="{% url 'package_included_reverse_dependencies' extra.build.pk extra.target_id data.pk %}">
> +      {{data.name}}</a>
> +      {% else %}
> +      {{data.name}}
> +      {% endif %}
> +      </strong>
> +      dependencies -
> +      <strong>{{package_deps.size|filtered_filesizeformat}}</strong>'>
> +      {{count_package}}
> +  </a>
>  {% endif %}
> +
> +{% endwith %}
>  {% endwith %}
> diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
> index 1d68036..119311d 100644
> --- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
> +++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
> @@ -297,3 +297,11 @@ def cut_path_prefix(fullpath, prefixes):
>          if fullpath.startswith(prefix):
>              return relpath(fullpath, prefix)
>      return fullpath
> +
> +
> + at register.filter
> +def for_target(package_dependencies, target):
> +    """ filter the dependencies to be displayed by the supplied target
> +    if no dependences are found for the target then return the predicted
> +    dependences"""
> +    return package_dependencies.for_target_or_none(target)
> diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
> index 88bc39a..1f908ea 100755
> --- a/bitbake/lib/toaster/toastergui/views.py
> +++ b/bitbake/lib/toaster/toastergui/views.py
> @@ -2060,7 +2060,9 @@ if True:
>  
>                  # Dependencies for package which aren't satisfied by the
>                  # current packages in the custom image recipe
> -                deps = package.package_dependencies_source.annotate(
> +                deps =\
> +                    package.package_dependencies_source.for_target_or_none(
> +                        recipe.name)['packages'].annotate(
>                      name=F('depends_on__name'),
>                      pk=F('depends_on__pk'),
>                      size=F('depends_on__size'),
> -- 
> 2.6.6
> 

-- 
--
Regards,
Ed


More information about the toaster mailing list