All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Toaster patches
@ 2015-08-18 16:28 Michael Wood
  2015-08-18 16:28 ` [PATCH 01/14] bitbake: toaster: pylint fixes Michael Wood
                   ` (13 more replies)
  0 siblings, 14 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 2077 bytes --]

Various bug fixes and pylint fixes. Reviewed by Belén and Michael.

The following changes since commit c348fa50186fb0796bc7b793c4b8d710419f2a0d:

  bitbake: toaster: move code from setup_lv_tests to setUp (2015-08-17 14:41:45 +0100)

are available in the git repository at:

  git://git.yoctoproject.org/poky-contrib michaelw/toaster/submit/adamian/20150817_bug_fixes_poky
  http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=michaelw/toaster/submit/adamian/20150817_bug_fixes_poky

Alexandru DAMIAN (13):
  bitbake: toaster: pylint fixes
  bitbake: toaster: checksettings: fix guesspath initialization
  bitbake: toaster: checksettings: fix TEMPLATECONF detection
  bitbake: toaster: improve exception handling
  bitbake: toaster: models field initialization
  bitbake: toaster: use loggers instead of prints
  bitbake: toastergui: rename variables in views.py
  bitbake: toaster: do not stop data import on bad data
  bitbake: toaster: replace raising Exceptions in loadconf
  bitbake: toaster: fix updates on failed build requests
  bitbake: toaster logger: fix pylint issues
  toastergui: do not show in-progress builds in the table
  toastergui: fix projectbuilds page

Alexandru Damian (1):
  bitbake: toaster: fix pylint errors

 lib/bb/ui/buildinfohelper.py                       | 130 ++++++++-------
 lib/bb/ui/toasterui.py                             |  62 ++++---
 lib/toaster/bldcontrol/bbcontroller.py             |   2 +-
 .../management/commands/checksettings.py           |  15 +-
 .../bldcontrol/management/commands/loadconf.py     |  37 +++--
 .../bldcontrol/management/commands/runbuilds.py    |   2 +-
 lib/toaster/orm/models.py                          |  80 ++++-----
 .../toastergui/templates/projectbuilds.html        |  42 +----
 lib/toaster/toastergui/views.py                    | 183 +++++++++++----------
 lib/toaster/toastergui/widgets.py                  |   3 +
 .../toastermain/management/commands/perf.py        |   7 +-
 11 files changed, 293 insertions(+), 270 deletions(-)

-- 
2.1.4



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/14] bitbake: toaster: pylint fixes
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 02/14] bitbake: toaster: checksettings: fix guesspath initialization Michael Wood
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

This patch fixes imports, default parameters to functions,
incorrect overloading and exception handling issues
highlighted by pylint. There are no functional changes.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 .../management/commands/checksettings.py           |  3 +-
 lib/toaster/orm/models.py                          |  1 -
 lib/toaster/toastergui/views.py                    | 32 +++++++++-------------
 3 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/lib/toaster/bldcontrol/management/commands/checksettings.py b/lib/toaster/bldcontrol/management/commands/checksettings.py
index 9a508b4..508335f 100644
--- a/lib/toaster/bldcontrol/management/commands/checksettings.py
+++ b/lib/toaster/bldcontrol/management/commands/checksettings.py
@@ -4,6 +4,7 @@ from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdExcep
 from bldcontrol.models import BuildRequest, BuildEnvironment, BRError
 from orm.models import ToasterSetting, Build
 import os
+import sys, traceback
 
 def DN(path):
     if path is None:
@@ -228,7 +229,7 @@ class Command(NoArgsCommand):
 
 
 
-    def handle(self, **options):
+    def handle_noargs(self, **options):
         retval = 0
         retval += self._verify_artifact_storage_dir()
         retval += self._verify_build_environment()
diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index 4f07e37..b3f8db9 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -807,7 +807,6 @@ class LayerIndexLayerSource(LayerSource):
             Fetches layer, recipe and machine information from remote repository
         """
         assert self.apiurl is not None
-        from django.db import IntegrityError
         from django.db import transaction, connection
 
         import httplib, urlparse, json
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 889b6c6..7be7f71 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -102,8 +102,7 @@ def _project_recent_build_list(prj):
 
 def objtojson(obj):
     from django.db.models.query import QuerySet
-    from django.db.models import Model, IntegerField
-    from django.db.models.fields.related import ForeignKey
+    from django.db.models import Model
 
     if isinstance(obj, datetime):
         return obj.isoformat()
@@ -266,8 +265,8 @@ def _get_filtering_query(filter_string):
 
     return reduce(operator.and_, [k for k in and_query])
 
-def _get_toggle_order(request, orderkey, reverse = False):
-    if reverse:
+def _get_toggle_order(request, orderkey, toggle_reverse = False):
+    if toggle_reverse:
         return "%s:+" % orderkey if request.GET.get('orderby', "") == "%s:-" % orderkey else "%s:-" % orderkey
     else:
         return "%s:-" % orderkey if request.GET.get('orderby', "") == "%s:+" % orderkey else "%s:+" % orderkey
@@ -522,7 +521,9 @@ def builddashboard( request, build_id ):
 
 
 
-def generateCoveredList2( revlist = [] ):
+def generateCoveredList2( revlist = None ):
+    if revlist is None:
+        revlist = []
     covered_list =  [ x for x in revlist if x.outcome == Task.OUTCOME_COVERED ]
     while len(covered_list):
         revlist =  [ x for x in revlist if x.outcome != Task.OUTCOME_COVERED ]
@@ -910,9 +911,7 @@ def _get_dir_entries(build_id, target_id, start):
 
         except Exception as e:
             print "Exception ", e
-            import traceback
             traceback.print_exc(e)
-            pass
 
     # sort by directories first, then by name
     rsorted = sorted(response, key=lambda entry :  entry['name'])
@@ -936,7 +935,7 @@ def dirinfo(request, build_id, target_id, file_path=None):
         dir_list = []
         head = file_path
         while head != sep:
-            (head,tail) = os.path.split(head)
+            (head, tail) = os.path.split(head)
             if head != sep:
                 dir_list.insert(0, head)
 
@@ -1837,7 +1836,6 @@ def image_information_dir(request, build_id, target_id, packagefile_id):
 
 
 def managedcontextprocessor(request):
-    import subprocess
     ret = {
         "projects": Project.objects.all(),
         "DEBUG" : toastermain.settings.DEBUG,
@@ -1865,13 +1863,9 @@ if True:
 
     import traceback
 
-    class BadParameterException(Exception): pass        # error thrown on invalid POST requests
-
-
-    class InvalidRequestException(Exception):
-        def __init__(self, response):
-            self.response = response
-
+    class BadParameterException(Exception):
+        ''' The exception raised on invalid POST requests '''
+        pass
 
     # shows the "all builds" page for managed mode; it displays build requests (at least started!) instead of actual builds
     @_template_renderer("builds.html")
@@ -2474,7 +2468,7 @@ if True:
         try:
             layer_version_id = request.POST["layer_version_id"]
             layer_version = Layer_Version.objects.get(id=layer_version_id)
-        except:
+        except Layer_Version.DoesNotExist:
             return error_response("Cannot find layer to update")
 
 
@@ -2503,8 +2497,8 @@ if True:
         try:
             layer_version.layer.save()
             layer_version.save()
-        except:
-            return error_response("Could not update layer version entry")
+        except Exception as e:
+            return error_response("Could not update layer version entry: %s" % e)
 
         return HttpResponse(jsonfilter({"error": "ok",}), content_type = "application/json")
 
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/14] bitbake: toaster: checksettings: fix guesspath initialization
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
  2015-08-18 16:28 ` [PATCH 01/14] bitbake: toaster: pylint fixes Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 03/14] bitbake: toaster: checksettings: fix TEMPLATECONF detection Michael Wood
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

Object fields need to be instantiated in the constructor.
Fixed prompted by pylint.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/bldcontrol/management/commands/checksettings.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/toaster/bldcontrol/management/commands/checksettings.py b/lib/toaster/bldcontrol/management/commands/checksettings.py
index 508335f..2978db2 100644
--- a/lib/toaster/bldcontrol/management/commands/checksettings.py
+++ b/lib/toaster/bldcontrol/management/commands/checksettings.py
@@ -17,6 +17,9 @@ class Command(NoArgsCommand):
     args = ""
     help = "Verifies that the configured settings are valid and usable, or prompts the user to fix the settings."
 
+    def __init__(self, *args, **kwargs):
+        super(Command, self).__init__(*args, **kwargs)
+        self.guesspath = DN(DN(DN(DN(DN(DN(DN(__file__)))))))
 
     def _find_first_path_for_file(self, startdirectory, filename, level = 0):
         if level < 0:
@@ -83,7 +86,6 @@ class Command(NoArgsCommand):
 
 
     def _verify_build_environment(self):
-        self.guesspath = DN(DN(DN(DN(DN(DN(DN(__file__)))))))
         # refuse to start if we have no build environments
         while BuildEnvironment.objects.count() == 0:
             print(" !! No build environments found. Toaster needs at least one build environment in order to be able to run builds.\n" +
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/14] bitbake: toaster: checksettings: fix TEMPLATECONF detection
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
  2015-08-18 16:28 ` [PATCH 01/14] bitbake: toaster: pylint fixes Michael Wood
  2015-08-18 16:28 ` [PATCH 02/14] bitbake: toaster: checksettings: fix guesspath initialization Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 04/14] bitbake: toaster: improve exception handling Michael Wood
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

Improving the TEMPLATECONF detection by verifying the return
code and dumping extra debug information in case of exception.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/bldcontrol/management/commands/checksettings.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/toaster/bldcontrol/management/commands/checksettings.py b/lib/toaster/bldcontrol/management/commands/checksettings.py
index 2978db2..83b4f28 100644
--- a/lib/toaster/bldcontrol/management/commands/checksettings.py
+++ b/lib/toaster/bldcontrol/management/commands/checksettings.py
@@ -166,7 +166,12 @@ class Command(NoArgsCommand):
                     for dirname in self._recursive_list_directories(be.sourcedir,2):
                         if os.path.exists(os.path.join(dirname, ".templateconf")):
                             import subprocess
-                            conffilepath, error = subprocess.Popen('bash -c ". '+os.path.join(dirname, ".templateconf")+'; echo \"\$TEMPLATECONF\""', shell=True, stdout=subprocess.PIPE).communicate()
+                            proc = subprocess.Popen('bash -c ". '+os.path.join(dirname, ".templateconf")+'; echo \"\$TEMPLATECONF\""', shell=True, stdout=subprocess.PIPE)
+                            conffilepath, stderroroutput = proc.communicate()
+                            proc.wait()
+                            if proc.returncode != 0:
+                                raise Exception("Failed to source TEMPLATECONF: %s" % stderroroutput)
+
                             conffilepath = os.path.join(conffilepath.strip(), "toasterconf.json")
                             candidatefilepath = os.path.join(dirname, conffilepath)
                             if "toaster_cloned" in candidatefilepath:
@@ -195,6 +200,7 @@ class Command(NoArgsCommand):
                                     return is_changed
                         except Exception as e:
                             print "Failure while trying to import the toaster config file: %s" % e
+                            traceback.print_exc(e)
                     else:
                         print "\n Toaster could not find a configuration file. You need to configure Toaster manually using the web interface, or create a configuration file and use\n  bitbake/lib/toaster/managepy.py loadconf [filename]\n command to load it. You can use https://wiki.yoctoproject.org/wiki/File:Toasterconf.json.txt.patch as a starting point."
 
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/14] bitbake: toaster: improve exception handling
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (2 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 03/14] bitbake: toaster: checksettings: fix TEMPLATECONF detection Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 05/14] bitbake: toaster: models field initialization Michael Wood
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

This patch improves exception handling, fixing issues
as prompted by pylint, including exception renaming.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/orm/models.py       | 15 ++++++---------
 lib/toaster/toastergui/views.py | 13 ++++---------
 2 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index b3f8db9..6b485d2 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -269,11 +269,10 @@ class Project(models.Model):
             except ProjectVariable.DoesNotExist:
                 pass
             br.save()
-        except Exception as e:
+        except Exception:
+            # revert the build request creation since we're not done cleanly
             br.delete()
-            import sys
-            et, ei, tb = sys.exc_info()
-            raise type(e), e, tb
+            raise
         return br
 
 class Build(models.Model):
@@ -364,7 +363,7 @@ class BuildArtifact(models.Model):
 
 
     def is_available(self):
-        return build.buildrequest.environment.has_artifact(file_path)
+        return self.build.buildrequest.environment.has_artifact(self.file_name)
 
 class ProjectTarget(models.Model):
     project = models.ForeignKey(Project)
@@ -981,12 +980,10 @@ class LayerIndexLayerSource(LayerSource):
                 if 'inherits' in ri:
                     ro.is_image = 'image' in ri['inherits'].split()
                 ro.save()
-            except:
-                #print "Duplicate Recipe, ignoring: ", vars(ro)
-                pass
+            except Exception:
+                logger.warning("Duplicate Recipe, ignoring: %s " % vars(ro))
         if not connection.features.autocommits_when_autocommit_is_off:
             transaction.set_autocommit(True)
-        pass
 
 class BitbakeVersion(models.Model):
 
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 7be7f71..5cee068 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -1876,10 +1876,7 @@ if True:
 
         queryset = Build.objects.filter(outcome__lte = Build.IN_PROGRESS)
 
-        try:
-            context, pagesize, orderby = _build_list_helper(request, queryset)
-        except InvalidRequestException as e:
-            raise RedirectException( builds, request.GET, e.response)
+        context, pagesize, orderby = _build_list_helper(request, queryset)
 
         _set_parameters_values(pagesize, orderby, request)
         return context
@@ -2422,7 +2419,8 @@ if True:
                         # dependency already (like modified on another page)
                         try:
                             prj_layer, prj_layer_created = ProjectLayer.objects.get_or_create(layercommit=layer_dep_obj, project=prj)
-                        except:
+                        except IntegrityError as e:
+                            logger.warning("Integrity error while saving Project Layers: %s (original %s)" % (e, e.__cause__))
                             continue
 
                         if prj_layer_created:
@@ -2639,10 +2637,7 @@ if True:
 
         queryset = Build.objects.filter(outcome__lte = Build.IN_PROGRESS)
 
-        try:
-            context, pagesize, orderby = _build_list_helper(request, queryset)
-        except InvalidRequestException as e:
-            raise RedirectException('projectbuilds', request.GET, e.response, pid = pid)
+        context, pagesize, orderby = _build_list_helper(request, queryset)
 
         context['project'] = prj
         _set_parameters_values(pagesize, orderby, request)
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/14] bitbake: toaster: models field initialization
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (3 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 04/14] bitbake: toaster: improve exception handling Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 06/14] bitbake: toaster: use loggers instead of prints Michael Wood
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

As prompted by pylint, the object fields need to be
initialized properly, so this patch fixes that.

Also adds some casts to int, because, sometimes, the IntegerField
is not returning an int, but a string.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/orm/models.py | 38 +++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index 6b485d2..26abf37 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -472,20 +472,27 @@ class Task(models.Model):
 
     search_allowed_fields = [ "recipe__name", "recipe__version", "task_name", "logfile" ]
 
+    def __init__(self, *args, **kwargs):
+        super(Task, self).__init__(*args, **kwargs)
+        try:
+            self._helptext = HelpText.objects.get(key=self.task_name, area=HelpText.VARIABLE, build=self.build).text
+        except HelpText.DoesNotExist:
+            self._helptext = None
+
     def get_related_setscene(self):
         return Task.objects.filter(task_executed=True, build = self.build, recipe = self.recipe, task_name=self.task_name+"_setscene")
 
     def get_outcome_text(self):
-        return Task.TASK_OUTCOME[self.outcome + 1][1]
+        return Task.TASK_OUTCOME[int(self.outcome) + 1][1]
 
     def get_outcome_help(self):
-        return Task.TASK_OUTCOME_HELP[self.outcome][1]
+        return Task.TASK_OUTCOME_HELP[int(self.outcome)][1]
 
     def get_sstate_text(self):
         if self.sstate_result==Task.SSTATE_NA:
             return ''
         else:
-            return Task.SSTATE_RESULT[self.sstate_result][1]
+            return Task.SSTATE_RESULT[int(self.sstate_result)][1]
 
     def get_executed_display(self):
         if self.task_executed:
@@ -493,13 +500,6 @@ class Task(models.Model):
         return "Not Executed"
 
     def get_description(self):
-        if '_helptext' in vars(self) and self._helptext != None:
-            return self._helptext
-        try:
-            self._helptext = HelpText.objects.get(key=self.task_name, area=HelpText.VARIABLE, build=self.build).text
-        except HelpText.DoesNotExist:
-            self._helptext = None
-
         return self._helptext
 
     build = models.ForeignKey(Build, related_name='task_build')
@@ -721,13 +721,8 @@ class LayerSource(models.Model):
     sourcetype = models.IntegerField(choices=SOURCE_TYPE)
     apiurl = models.CharField(max_length=255, null=True, default=None)
 
-    def update(self):
-        """
-            Updates the local database information from the upstream layer source
-        """
-        raise Exception("Abstract, update() must be implemented by all LayerSource-derived classes (object is %s)" % str(vars(self)))
-
-    def save(self, *args, **kwargs):
+    def __init__(self, *args, **kwargs):
+        super(LayerSource, self).__init__(*args, **kwargs)
         if self.sourcetype == LayerSource.TYPE_LOCAL:
             self.__class__ = LocalLayerSource
         elif self.sourcetype == LayerSource.TYPE_LAYERINDEX:
@@ -736,6 +731,15 @@ class LayerSource(models.Model):
             self.__class__ = ImportedLayerSource
         elif self.sourcetype == None:
             raise Exception("Unknown LayerSource-derived class. If you added a new layer source type, fill out all code stubs.")
+
+
+    def update(self):
+        """
+            Updates the local database information from the upstream layer source
+        """
+        raise Exception("Abstract, update() must be implemented by all LayerSource-derived classes (object is %s)" % str(vars(self)))
+
+    def save(self, *args, **kwargs):
         return super(LayerSource, self).save(*args, **kwargs)
 
     def get_object(self):
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/14] bitbake: toaster: use loggers instead of prints
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (4 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 05/14] bitbake: toaster: models field initialization Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 07/14] bitbake: toastergui: rename variables in views.py Michael Wood
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

Switching debugging from using print statement to using
loggers, as it uses the logging infrastructure to process
the messages.

The messages are logged with the "toaster" logger which
is defined in the toastermain/settings.py.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/orm/models.py       | 22 +++++++++++++---------
 lib/toaster/toastergui/views.py |  4 ++++
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index 26abf37..c3fb766 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -29,6 +29,11 @@ from django.core import validators
 from django.conf import settings
 import django.db.models.signals
 
+
+import logging
+logger = logging.getLogger("toaster")
+
+
 class GitURLValidator(validators.URLValidator):
     import re
     regex = re.compile(
@@ -855,8 +860,8 @@ class LayerIndexLayerSource(LayerSource):
         except Exception as e:
             import traceback
             if proxy_settings is not None:
-                print "EE: Using proxy ", proxy_settings
-            print "EE: could not connect to %s, skipping update: %s\n%s" % (self.apiurl, e, traceback.format_exc(e))
+                logger.info("EE: Using proxy %s" % proxy_settings)
+            logger.warning("EE: could not connect to %s, skipping update: %s\n%s" % (self.apiurl, e, traceback.format_exc(e)))
             return
 
         # update branches; only those that we already have names listed in the
@@ -865,7 +870,7 @@ class LayerIndexLayerSource(LayerSource):
         if len(whitelist_branch_names) == 0:
             raise Exception("Failed to make list of branches to fetch")
 
-        print "Fetching branches"
+        logger.debug("Fetching branches")
         branches_info = _get_json_response(apilinks['branches']
             + "?filter=name:%s" % "OR".join(whitelist_branch_names))
         for bi in branches_info:
@@ -895,7 +900,7 @@ class LayerIndexLayerSource(LayerSource):
             transaction.set_autocommit(True)
 
         # update layerbranches/layer_versions
-        print "Fetching layer information"
+        logger.debug("Fetching layer information")
         layerbranches_info = _get_json_response(apilinks['layerBranches']
                 + "?filter=branch:%s" % "OR".join(map(lambda x: str(x.up_id), [i for i in Branch.objects.filter(layer_source = self) if i.up_id is not None] ))
             )
@@ -933,7 +938,7 @@ class LayerIndexLayerSource(LayerSource):
             try:
                 dependlist[lv].append(Layer_Version.objects.get(layer_source = self, layer__up_id = ldi['dependency'], up_branch = lv.up_branch))
             except Layer_Version.DoesNotExist:
-                print "Cannot find layer version ", self, ldi['dependency'], lv.up_branch
+                logger.warning("Cannot find layer version %s dep:%s up_brach:%s" % (self, ldi['dependency'], lv.up_branch))
 
         for lv in dependlist:
             LayerVersionDependency.objects.filter(layer_version = lv).delete()
@@ -944,7 +949,7 @@ class LayerIndexLayerSource(LayerSource):
 
 
         # update machines
-        print "Fetching machine information"
+        logger.debug("Fetching machine information")
         machines_info = _get_json_response(apilinks['machines']
                 + "?filter=layerbranch:%s" % "OR".join(map(lambda x: str(x.up_id), Layer_Version.objects.filter(layer_source = self)))
             )
@@ -962,7 +967,7 @@ class LayerIndexLayerSource(LayerSource):
             transaction.set_autocommit(True)
 
         # update recipes; paginate by layer version / layer branch
-        print "Fetching target information"
+        logger.debug("Fetching target information")
         recipes_info = _get_json_response(apilinks['recipes']
                 + "?filter=layerbranch:%s" % "OR".join(map(lambda x: str(x.up_id), Layer_Version.objects.filter(layer_source = self)))
             )
@@ -1236,8 +1241,7 @@ def invalidate_cache(**kwargs):
     try:
       cache.clear()
     except Exception as e:
-      print "Problem with cache backend: Failed to clear cache"
-      pass
+      logger.warning("Problem with cache backend: Failed to clear cache: %s" % e)
 
 django.db.models.signals.post_save.connect(invalidate_cache)
 django.db.models.signals.post_delete.connect(invalidate_cache)
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 5cee068..ddc7703 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -42,6 +42,10 @@ import json
 from os.path import dirname
 import itertools
 
+import logging
+
+logger = logging.getLogger("toaster")
+
 # all new sessions should come through the landing page;
 # determine in which mode we are running in, and redirect appropriately
 def landing(request):
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/14] bitbake: toastergui: rename variables in views.py
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (5 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 06/14] bitbake: toaster: use loggers instead of prints Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 08/14] bitbake: toaster: do not stop data import on bad data Michael Wood
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

Renaming various variables in the views.py file to make
the code more readable, and prevent overshadowing of global
variables with local variables that have a different name.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/toastergui/views.py | 116 ++++++++++++++++++++++------------------
 1 file changed, 63 insertions(+), 53 deletions(-)

diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index ddc7703..e9c246f 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -284,30 +284,30 @@ def _get_toggle_order_icon(request, orderkey):
         return None
 
 # we check that the input comes in a valid form that we can recognize
-def _validate_input(input, model):
+def _validate_input(field_input, model):
 
     invalid = None
 
-    if input:
-        input_list = input.split(FIELD_SEPARATOR)
+    if field_input:
+        field_input_list = field_input.split(FIELD_SEPARATOR)
 
         # Check we have only one colon
-        if len(input_list) != 2:
-            invalid = "We have an invalid number of separators: " + input + " -> " + str(input_list)
+        if len(field_input_list) != 2:
+            invalid = "We have an invalid number of separators: " + field_input + " -> " + str(field_input_list)
             return None, invalid
 
         # Check we have an equal number of terms both sides of the colon
-        if len(input_list[0].split(AND_VALUE_SEPARATOR)) != len(input_list[1].split(AND_VALUE_SEPARATOR)):
+        if len(field_input_list[0].split(AND_VALUE_SEPARATOR)) != len(field_input_list[1].split(AND_VALUE_SEPARATOR)):
             invalid = "Not all arg names got values"
-            return None, invalid + str(input_list)
+            return None, invalid + str(field_input_list)
 
         # Check we are looking for a valid field
         valid_fields = model._meta.get_all_field_names()
-        for field in input_list[0].split(AND_VALUE_SEPARATOR):
-            if not reduce(lambda x, y: x or y, map(lambda x: field.startswith(x), [ x for x in valid_fields ])):
+        for field in field_input_list[0].split(AND_VALUE_SEPARATOR):
+            if not reduce(lambda x, y: x or y, [ field.startswith(x) for x in valid_fields ]):
                 return None, (field, [ x for x in valid_fields ])
 
-    return input, invalid
+    return field_input, invalid
 
 # uses search_allowed_fields in orm/models.py to create a search query
 # for these fields with the supplied input text
@@ -542,23 +542,23 @@ def generateCoveredList2( revlist = None ):
 
 def task( request, build_id, task_id ):
     template = "task.html"
-    tasks = Task.objects.filter( pk=task_id )
-    if tasks.count( ) == 0:
+    tasks_list = Task.objects.filter( pk=task_id )
+    if tasks_list.count( ) == 0:
         return redirect( builds )
-    task = tasks[ 0 ];
+    task_object = tasks_list[ 0 ];
     dependencies = sorted(
-        _find_task_dep( task ),
+        _find_task_dep( task_object ),
         key=lambda t:'%s_%s %s'%(t.recipe.name, t.recipe.version, t.task_name))
     reverse_dependencies = sorted(
-        _find_task_revdep( task ),
+        _find_task_revdep( task_object ),
         key=lambda t:'%s_%s %s'%( t.recipe.name, t.recipe.version, t.task_name ))
     coveredBy = '';
-    if ( task.outcome == Task.OUTCOME_COVERED ):
+    if ( task_object.outcome == Task.OUTCOME_COVERED ):
 #        _list = generateCoveredList( task )
-        coveredBy = sorted(generateCoveredList2( _find_task_revdep( task ) ), key = lambda x: x.recipe.name)
+        coveredBy = sorted(generateCoveredList2( _find_task_revdep( task_object ) ), key = lambda x: x.recipe.name)
     log_head = ''
     log_body = ''
-    if task.outcome == task.OUTCOME_FAILED:
+    if task_object.outcome == task_object.OUTCOME_FAILED:
         pass
 
     uri_list= [ ]
@@ -570,12 +570,13 @@ def task( request, build_id, task_id ):
     if (v.count() > 0):
         for mirror in v[0].variable_value.split('\\n'):
             s=re.sub('.* ','',mirror.strip(' \t\n\r'))
-            if len(s): uri_list.append(s)
+            if len(s):
+                uri_list.append(s)
 
     context = {
             'build'           : Build.objects.filter( pk = build_id )[ 0 ],
-            'object'          : task,
-            'task'            : task,
+            'object'          : task_object,
+            'task'            : task_object,
             'covered_by'      : coveredBy,
             'deps'            : dependencies,
             'rdeps'           : reverse_dependencies,
@@ -587,8 +588,8 @@ def task( request, build_id, task_id ):
     if request.GET.get( 'show_matches', "" ):
         context[ 'showing_matches' ] = True
         context[ 'matching_tasks' ] = Task.objects.filter(
-            sstate_checksum=task.sstate_checksum ).filter(
-            build__completed_on__lt=task.build.completed_on).exclude(
+            sstate_checksum=task_object.sstate_checksum ).filter(
+            build__completed_on__lt=task_object.build.completed_on).exclude(
             order__isnull=True).exclude(outcome=Task.OUTCOME_NA).order_by('-build__completed_on')
 
     return render( request, template, context )
@@ -598,10 +599,10 @@ def recipe(request, build_id, recipe_id, active_tab="1"):
     if Recipe.objects.filter(pk=recipe_id).count() == 0 :
         return redirect(builds)
 
-    object = Recipe.objects.get(pk=recipe_id)
-    layer_version = Layer_Version.objects.get(pk=object.layer_version_id)
+    recipe_object = Recipe.objects.get(pk=recipe_id)
+    layer_version = Layer_Version.objects.get(pk=recipe_object.layer_version_id)
     layer  = Layer.objects.get(pk=layer_version.layer_id)
-    tasks  = Task.objects.filter(recipe_id = recipe_id, build_id = build_id).exclude(order__isnull=True).exclude(task_name__endswith='_setscene').exclude(outcome=Task.OUTCOME_NA)
+    tasks_list  = Task.objects.filter(recipe_id = recipe_id, build_id = build_id).exclude(order__isnull=True).exclude(task_name__endswith='_setscene').exclude(outcome=Task.OUTCOME_NA)
     package_count = Package.objects.filter(recipe_id = recipe_id).filter(build_id = build_id).filter(size__gte=0).count()
 
     if active_tab != '1' and active_tab != '3' and active_tab != '4' :
@@ -611,10 +612,10 @@ def recipe(request, build_id, recipe_id, active_tab="1"):
 
     context = {
             'build'   : Build.objects.get(pk=build_id),
-            'object'  : object,
+            'object'  : recipe_object,
             'layer_version' : layer_version,
             'layer'   : layer,
-            'tasks'   : tasks,
+            'tasks'   : tasks_list,
             'package_count' : package_count,
             'tab_states' : tab_states,
     }
@@ -632,7 +633,7 @@ def recipe_packages(request, build_id, recipe_id):
         return _redirect_parameters( 'recipe_packages', request.GET, mandatory_parameters, build_id = build_id, recipe_id = recipe_id)
     (filter_string, search_term, ordering_string) = _search_tuple(request, Package)
 
-    recipe = Recipe.objects.get(pk=recipe_id)
+    recipe_object = Recipe.objects.get(pk=recipe_id)
     queryset = Package.objects.filter(recipe_id = recipe_id).filter(build_id = build_id).filter(size__gte=0)
     package_count = queryset.count()
     queryset = _get_queryset(Package, queryset, filter_string, search_term, ordering_string, 'name')
@@ -641,7 +642,7 @@ def recipe_packages(request, build_id, recipe_id):
 
     context = {
             'build'   : Build.objects.get(pk=build_id),
-            'recipe'  : recipe,
+            'recipe'  : recipe_object,
             'objects'  : packages,
             'object_count' : package_count,
             'tablecols':[
@@ -952,13 +953,13 @@ def dirinfo(request, build_id, target_id, file_path=None):
               }
     return render(request, template, context)
 
-def _find_task_dep(task):
-    return map(lambda x: x.depends_on, Task_Dependency.objects.filter(task=task).filter(depends_on__order__gt = 0).exclude(depends_on__outcome = Task.OUTCOME_NA).select_related("depends_on"))
+def _find_task_dep(task_object):
+    return map(lambda x: x.depends_on, Task_Dependency.objects.filter(task=task_object).filter(depends_on__order__gt = 0).exclude(depends_on__outcome = Task.OUTCOME_NA).select_related("depends_on"))
 
 
-def _find_task_revdep(task):
+def _find_task_revdep(task_object):
     tp = []
-    tp = map(lambda t: t.task, Task_Dependency.objects.filter(depends_on=task).filter(task__order__gt=0).exclude(task__outcome = Task.OUTCOME_NA).select_related("task", "task__recipe", "task__build"))
+    tp = map(lambda t: t.task, Task_Dependency.objects.filter(depends_on=task_object).filter(task__order__gt=0).exclude(task__outcome = Task.OUTCOME_NA).select_related("task", "task__recipe", "task__build"))
     return tp
 
 def _find_task_revdep_list(tasklist):
@@ -966,8 +967,8 @@ def _find_task_revdep_list(tasklist):
     tp = map(lambda t: t.task, Task_Dependency.objects.filter(depends_on__in=tasklist).filter(task__order__gt=0).exclude(task__outcome = Task.OUTCOME_NA).select_related("task", "task__recipe", "task__build"))
     return tp
 
-def _find_task_provider(task):
-    task_revdeps = _find_task_revdep(task)
+def _find_task_provider(task_object):
+    task_revdeps = _find_task_revdep(task_object)
     for tr in task_revdeps:
         if tr.outcome != Task.OUTCOME_COVERED:
             return tr
@@ -1055,15 +1056,15 @@ def tasks_common(request, build_id, variant, task_anchor):
         i=0
         a=int(anchor)
         count_per_page=int(pagesize)
-        for task in queryset.iterator():
-            if a == task.order:
+        for task_object in queryset.iterator():
+            if a == task_object.order:
                 new_page= (i / count_per_page ) + 1
                 request.GET.__setitem__('page', new_page)
                 mandatory_parameters['page']=new_page
                 return _redirect_parameters( variant, request.GET, mandatory_parameters, build_id = build_id)
             i += 1
 
-    tasks = _build_page_range(Paginator(queryset, pagesize),request.GET.get('page', 1))
+    task_objects = _build_page_range(Paginator(queryset, pagesize),request.GET.get('page', 1))
 
     # define (and modify by variants) the 'tablecols' members
     tc_order={
@@ -1073,7 +1074,10 @@ def tasks_common(request, build_id, variant, task_anchor):
         'orderkey' : 'order',
         'orderfield':_get_toggle_order(request, "order"),
         'ordericon':_get_toggle_order_icon(request, "order")}
-    if 'tasks' == variant: tc_order['hidden']='0'; del tc_order['clclass']
+    if 'tasks' == variant:
+        tc_order['hidden']='0'
+        del tc_order['clclass']
+
     tc_recipe={
         'name':'Recipe',
         'qhelp':'The name of the recipe to which each task applies',
@@ -1131,14 +1135,7 @@ def tasks_common(request, build_id, variant, task_anchor):
                    }
 
     }
-    tc_log={
-        'name':'Log',
-        'qhelp':'Path to the task log file',
-        'orderfield': _get_toggle_order(request, "logfile"),
-        'ordericon':_get_toggle_order_icon(request, "logfile"),
-        'orderkey' : 'logfile',
-        'clclass': 'task_log', 'hidden' : 1,
-    }
+
     tc_cache={
         'name':'Cache attempt',
         'qhelp':'This column tells you if a task tried to restore output from the <code>sstate-cache</code> directory or mirrors, and reports the result: Succeeded, Failed or File not in cache',
@@ -1167,7 +1164,11 @@ def tasks_common(request, build_id, variant, task_anchor):
         'orderkey' : 'elapsed_time',
         'clclass': 'time_taken', 'hidden' : 1,
     }
-    if   'buildtime' == variant: tc_time['hidden']='0'; del tc_time['clclass']; tc_cache['hidden']='1';
+    if 'buildtime' == variant:
+        tc_time['hidden']='0'
+        del tc_time['clclass']
+        tc_cache['hidden']='1'
+
     tc_cpu={
         'name':'CPU usage',
         'qhelp':'The percentage of task CPU utilization',
@@ -1176,7 +1177,12 @@ def tasks_common(request, build_id, variant, task_anchor):
         'orderkey' : 'cpu_usage',
         'clclass': 'cpu_used', 'hidden' : 1,
     }
-    if   'cpuusage' == variant: tc_cpu['hidden']='0'; del tc_cpu['clclass']; tc_cache['hidden']='1';
+
+    if  'cpuusage' == variant:
+        tc_cpu['hidden']='0'
+        del tc_cpu['clclass']
+        tc_cache['hidden']='1'
+
     tc_diskio={
         'name':'Disk I/O (ms)',
         'qhelp':'Number of miliseconds the task spent doing disk input and output',
@@ -1185,7 +1191,10 @@ def tasks_common(request, build_id, variant, task_anchor):
         'orderkey' : 'disk_io',
         'clclass': 'disk_io', 'hidden' : 1,
     }
-    if   'diskio' == variant: tc_diskio['hidden']='0'; del tc_diskio['clclass']; tc_cache['hidden']='1';
+    if 'diskio' == variant:
+        tc_diskio['hidden']='0'
+        del tc_diskio['clclass']
+        tc_cache['hidden']='1'
 
     build = Build.objects.get(pk=build_id)
 
@@ -1194,7 +1203,7 @@ def tasks_common(request, build_id, variant, task_anchor):
                 'filter_search_display': filter_search_display,
                 'title': title_variant,
                 'build': build,
-                'objects': tasks,
+                'objects': task_objects,
                 'default_orderby' : orderby,
                 'search_term': search_term,
                 'total_count': queryset_with_search.count(),
@@ -1246,7 +1255,8 @@ def recipes(request, build_id):
     recipes = _build_page_range(Paginator(queryset, pagesize),request.GET.get('page', 1))
 
     # prefetch the forward and reverse recipe dependencies
-    deps = { }; revs = { }
+    deps = { }
+    revs = { }
     queryset_dependency=Recipe_Dependency.objects.filter(recipe__layer_version__build_id = build_id).select_related("depends_on", "recipe")
     for recipe in recipes:
         deplist = [ ]
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/14] bitbake: toaster: do not stop data import on bad data
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (6 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 07/14] bitbake: toastergui: rename variables in views.py Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 09/14] bitbake: toaster: replace raising Exceptions in loadconf Michael Wood
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

The layer data update in Layer source needlessly stops
processing by throwing an Exception when bad layer data cannot
be inserted in the database (e.g. invalid dependencies).

This patch changes the behaviour to ignore bad data, and
continue with data import after detailed logging through the
logging system.

[YOCTO #7955]

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/orm/models.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index c3fb766..de00702 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -19,7 +19,7 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-from django.db import models
+from django.db import models, IntegrityError
 from django.db.models import F, Q, Avg, Max
 from django.utils import timezone
 
@@ -938,7 +938,7 @@ class LayerIndexLayerSource(LayerSource):
             try:
                 dependlist[lv].append(Layer_Version.objects.get(layer_source = self, layer__up_id = ldi['dependency'], up_branch = lv.up_branch))
             except Layer_Version.DoesNotExist:
-                logger.warning("Cannot find layer version %s dep:%s up_brach:%s" % (self, ldi['dependency'], lv.up_branch))
+                logger.warning("Cannot find layer version (ls:%s), up_id:%s lv:%s" % (self, ldi['dependency'], lv))
 
         for lv in dependlist:
             LayerVersionDependency.objects.filter(layer_version = lv).delete()
@@ -989,8 +989,8 @@ class LayerIndexLayerSource(LayerSource):
                 if 'inherits' in ri:
                     ro.is_image = 'image' in ri['inherits'].split()
                 ro.save()
-            except Exception:
-                logger.warning("Duplicate Recipe, ignoring: %s " % vars(ro))
+            except IntegrityError as e:
+                logger.debug("Failed saving recipe, ignoring: %s (%s:%s)" % (e, ro.layer_version, ri['filepath']+"/"+ri['filename']))
         if not connection.features.autocommits_when_autocommit_is_off:
             transaction.set_autocommit(True)
 
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/14] bitbake: toaster: replace raising Exceptions in loadconf
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (7 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 08/14] bitbake: toaster: do not stop data import on bad data Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 10/14] bitbake: toaster: fix updates on failed build requests Michael Wood
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

This patch replaces throwing Exceptions in toaster loadconf
command with proper explicit error messages. This allows
the user to properly understand and debug what went wrong when
loading a config file.

Additionally we change a bit the logic around auto-detecting relative
giturl handling so the user gets proper error messages when
trying to load an invalid toasterconf.json file.

[YOCTO #7945]

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 .../bldcontrol/management/commands/loadconf.py     | 37 ++++++++++++++--------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/lib/toaster/bldcontrol/management/commands/loadconf.py b/lib/toaster/bldcontrol/management/commands/loadconf.py
index 9163e9b..5022b59 100644
--- a/lib/toaster/bldcontrol/management/commands/loadconf.py
+++ b/lib/toaster/bldcontrol/management/commands/loadconf.py
@@ -1,10 +1,14 @@
 from django.core.management.base import BaseCommand, CommandError
 from orm.models import LayerSource, ToasterSetting, Branch, Layer, Layer_Version
 from orm.models import BitbakeVersion, Release, ReleaseDefaultLayer, ReleaseLayerSourcePriority
+from django.db import IntegrityError
 import os
 
 from checksettings import DN
 
+import logging
+logger = logging.getLogger("toaster")
+
 def _reduce_canon_path(path):
     components = []
     for c in path.split("/"):
@@ -34,7 +38,7 @@ class Command(BaseCommand):
         if not os.path.exists(filepath) or not os.path.isfile(filepath):
             raise Exception("Failed to find toaster config file %s ." % filepath)
 
-        import json, pprint
+        import json
         data = json.loads(open(filepath, "r").read())
 
         # verify config file validity before updating settings
@@ -49,7 +53,7 @@ class Command(BaseCommand):
             cmd = subprocess.Popen("git remote -v", shell=True, cwd = os.path.dirname(filepath), stdout=subprocess.PIPE, stderr = subprocess.PIPE)
             (out,err) = cmd.communicate()
             if cmd.returncode != 0:
-                raise Exception("Error while importing layer vcs_url: git error: %s" % err)
+                logging.warning("Error while importing layer vcs_url: git error: %s" % err)
             for line in out.split("\n"):
                 try:
                     (name, path) = line.split("\t", 1)
@@ -59,16 +63,20 @@ class Command(BaseCommand):
                 except ValueError:
                     pass
             if url == None:
-                raise Exception("Error while looking for remote \"%s\" in \"%s\"" % (remote_name, out))
+                logging.warning("Error while looking for remote \"%s\" in \"%s\"" % (remote_name, out))
             return url
 
 
         # import bitbake data
         for bvi in data['bitbake']:
             bvo, created = BitbakeVersion.objects.get_or_create(name=bvi['name'])
-            bvo.giturl = bvi['giturl']
             if bvi['giturl'].startswith("remote:"):
                 bvo.giturl = _read_git_url_from_local_repository(bvi['giturl'])
+                if bvo.giturl is None:
+                    logger.error("The toaster config file references the local git repo, but Toaster cannot detect it.\nYour local configuration for bitbake version %s is invalid. Make sure that the toasterconf.json file is correct." % bvi['name'])
+
+            if bvo.giturl is None:
+                bvo.giturl = bvi['giturl']
             bvo.branch = bvi['branch']
             bvo.dirpath = bvi['dirpath']
             bvo.save()
@@ -89,13 +97,12 @@ class Command(BaseCommand):
             assert ((_get_id_for_sourcetype(lsi['sourcetype']) == LayerSource.TYPE_LAYERINDEX) or apiurl.startswith("/")), (lsi['sourcetype'],apiurl)
 
             try:
-                ls = LayerSource.objects.get(sourcetype = _get_id_for_sourcetype(lsi['sourcetype']), apiurl = apiurl)
-            except LayerSource.DoesNotExist:
-                ls = LayerSource.objects.create(
-                    name = lsi['name'],
-                    sourcetype = _get_id_for_sourcetype(lsi['sourcetype']),
-                    apiurl = apiurl
-                )
+                ls, created = LayerSource.objects.get_or_create(sourcetype = _get_id_for_sourcetype(lsi['sourcetype']), apiurl = apiurl)
+                ls.name = lsi['name']
+                ls.save()
+            except IntegrityError as e:
+                logger.warning("IntegrityError %s \nWhile setting name %s for layer source %s " % (e, lsi['name'], ls))
+
 
             layerbranches = []
             for branchname in lsi['branches']:
@@ -111,12 +118,14 @@ class Command(BaseCommand):
                         lo.local_path = _reduce_canon_path(os.path.join(ls.apiurl, layerinfo['local_path']))
 
                     if not os.path.exists(lo.local_path):
-                        raise Exception("Local layer path %s must exists." % lo.local_path)
+                        logger.error("Local layer path %s must exists. Are you trying to import a layer that does not exist ? Check your local toasterconf.json" % lo.local_path)
 
-                    lo.vcs_url = layerinfo['vcs_url']
                     if layerinfo['vcs_url'].startswith("remote:"):
                         lo.vcs_url = _read_git_url_from_local_repository(layerinfo['vcs_url'])
-                    else:
+                        if lo.vcs_url is None:
+                            logger.error("The toaster config file references the local git repo, but Toaster cannot detect it.\nYour local configuration for layer %s is invalid. Make sure that the toasterconf.json file is correct." % layerinfo['name'])
+
+                    if lo.vcs_url is None:
                         lo.vcs_url = layerinfo['vcs_url']
 
                     if 'layer_index_url' in layerinfo:
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/14] bitbake: toaster: fix updates on failed build requests
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (8 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 09/14] bitbake: toaster: replace raising Exceptions in loadconf Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 11/14] bitbake: toaster: fix pylint errors Michael Wood
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

The patch to fix the original mistake is wrong, in the sense
that a constant from the BuildRequest class is used on the build
object.

Fixing the patch to bring in the correct constant in.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/bldcontrol/management/commands/runbuilds.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/toaster/bldcontrol/management/commands/runbuilds.py b/lib/toaster/bldcontrol/management/commands/runbuilds.py
index e3a1fdb..c3e9b74 100644
--- a/lib/toaster/bldcontrol/management/commands/runbuilds.py
+++ b/lib/toaster/bldcontrol/management/commands/runbuilds.py
@@ -130,7 +130,7 @@ class Command(NoArgsCommand):
         # update all BuildRequests without a build created
         for br in BuildRequest.objects.filter(build = None):
             br.build = Build.objects.create(project = br.project, completed_on = br.updated, started_on = br.created)
-            br.build.outcome = BuildRequest.REQ_FAILED
+            br.build.outcome = Build.FAILED
             try:
                 br.build.machine = br.brvariable_set.get(name='MACHINE').value
             except BRVariable.DoesNotExist:
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/14] bitbake: toaster: fix pylint errors
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (9 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 10/14] bitbake: toaster: fix updates on failed build requests Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:28 ` [PATCH 12/14] bitbake: toaster logger: fix pylint issues Michael Wood
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru Damian <alexandru.damian@intel.com>

Prompted by issues discovered during running pylint on
the toaster sources, this patch fixes:

* missing import in toaster ui
* improper call of function in toaster ui (logger.debug)
* improper function definitions in bbcontroller
* invalid references to objects in bldcontrol.models
* proper initialization of object fields in ToasterTables

Also inhibiting specific pylint errors in files where
the problems are mis-identified.

Signed-off-by: Alexandru Damian <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/bb/ui/toasterui.py                              | 5 +++--
 lib/toaster/bldcontrol/bbcontroller.py              | 2 +-
 lib/toaster/orm/models.py                           | 2 +-
 lib/toaster/toastergui/views.py                     | 4 ++++
 lib/toaster/toastergui/widgets.py                   | 3 +++
 lib/toaster/toastermain/management/commands/perf.py | 7 ++++++-
 6 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/lib/bb/ui/toasterui.py b/lib/bb/ui/toasterui.py
index f30f89e..767bfab 100644
--- a/lib/bb/ui/toasterui.py
+++ b/lib/bb/ui/toasterui.py
@@ -21,6 +21,7 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 from __future__ import division
+import sys
 try:
     import bb
 except RuntimeError as exc:
@@ -255,10 +256,10 @@ def main(server, eventHandler, params ):
                 # we start a new build info
                 if buildinfohelper.brbe is not None:
 
-                    logger.debug(1, "ToasterUI under BuildEnvironment management - exiting after the build")
+                    logger.debug("ToasterUI under BuildEnvironment management - exiting after the build")
                     server.terminateServer()
                 else:
-                    logger.debug(1, "ToasterUI prepared for new build")
+                    logger.debug("ToasterUI prepared for new build")
                     errors = 0
                     warnings = 0
                     taskfailures = []
diff --git a/lib/toaster/bldcontrol/bbcontroller.py b/lib/toaster/bldcontrol/bbcontroller.py
index 9dd01e0..ad70ac8 100644
--- a/lib/toaster/bldcontrol/bbcontroller.py
+++ b/lib/toaster/bldcontrol/bbcontroller.py
@@ -177,7 +177,7 @@ class BuildEnvironmentController(object):
 
         return BitbakeController(self.connection)
 
-    def getArtifact(path):
+    def getArtifact(self, path):
         """ This call returns an artifact identified by the 'path'. How 'path' is interpreted as
             up to the implementing BEC. The return MUST be a REST URL where a GET will actually return
             the content of the artifact, e.g. for use as a "download link" in a web UI.
diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index de00702..92fcaa7 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -81,7 +81,7 @@ class ProjectManager(models.Manager):
 
         for rdl in release.releasedefaultlayer_set.all():
             try:
-                lv =Layer_Version.objects.filter(layer__name = rdl.layer_name, up_branch__name = release.branch_name)[0].get_equivalents_wpriority(prj)[0]
+                lv = Layer_Version.objects.filter(layer__name = rdl.layer_name, up_branch__name = release.branch_name)[0].get_equivalents_wpriority(prj)[0]
                 ProjectLayer.objects.create( project = prj,
                         layercommit = lv,
                         optional = False )
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index e9c246f..20f7cb3 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -19,6 +19,10 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
+# pylint: disable=method-hidden
+# Gives E:848, 4: An attribute defined in json.encoder line 162 hides this method (method-hidden)
+# which is an invalid warning
+
 import operator,re
 
 from django.db.models import F, Q, Sum, Count, Max
diff --git a/lib/toaster/toastergui/widgets.py b/lib/toaster/toastergui/widgets.py
index 2adf574..eb2914d 100644
--- a/lib/toaster/toastergui/widgets.py
+++ b/lib/toaster/toastergui/widgets.py
@@ -334,6 +334,9 @@ class ToasterTemplateView(TemplateView):
     # renders a instance in a template, or returns the context as json
     # the class-equivalent of the _template_renderer decorator for views
 
+    def __init__(self, *args, **kwargs):
+        super(ToasterTemplateView, self).__init__(*args, **kwargs)
+        self.context_entries = []
 
     def get(self, *args, **kwargs):
         if self.request.GET.get('format', None) == 'json':
diff --git a/lib/toaster/toastermain/management/commands/perf.py b/lib/toaster/toastermain/management/commands/perf.py
index d28f26a..71a48e9 100644
--- a/lib/toaster/toastermain/management/commands/perf.py
+++ b/lib/toaster/toastermain/management/commands/perf.py
@@ -2,7 +2,12 @@ from django.core.management.base import BaseCommand
 from django.test.client import Client
 import os, sys, re
 import requests
-import toastermain.settings as settings
+from django.conf import settings
+
+# pylint: disable=E1103
+# Instance of 'WSGIRequest' has no 'status_code' member
+# (but some types could not be inferred) (maybe-no-member)
+
 
 class Command(BaseCommand):
     help    = "Test the response time for all toaster urls"
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 12/14] bitbake: toaster logger: fix pylint issues
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (10 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 11/14] bitbake: toaster: fix pylint errors Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-20 12:55   ` Olof Johansson
  2015-08-18 16:28 ` [PATCH 13/14] toastergui: do not show in-progress builds in the table Michael Wood
  2015-08-18 16:29 ` [PATCH 14/14] toastergui: fix projectbuilds page Michael Wood
  13 siblings, 1 reply; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

This patch fixes pylint issues in the toaster build data logger,
toasterui. The following types of warnings are touched here:

* fixing imports
* unused variables are set to _
* logger calls now use lazy evaluation instead of formatting
the string
* correct whitespace identation
* removes unneeded "pass" statements, and extra parantheses
* disable specific pylint warnings when decideing to override
them

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/bb/ui/buildinfohelper.py | 130 +++++++++++++++++++++++--------------------
 lib/bb/ui/toasterui.py       |  57 +++++++++----------
 2 files changed, 98 insertions(+), 89 deletions(-)

diff --git a/lib/bb/ui/buildinfohelper.py b/lib/bb/ui/buildinfohelper.py
index cce6da5..09e8853 100644
--- a/lib/bb/ui/buildinfohelper.py
+++ b/lib/bb/ui/buildinfohelper.py
@@ -19,12 +19,20 @@
 import sys
 import bb
 import re
-import ast
+import os
 
 os.environ["DJANGO_SETTINGS_MODULE"] = "toaster.toastermain.settings"
 
+
 from django.utils import timezone
-import toaster.toastermain.settings as toaster_django_settings
+
+
+def _configure_toaster():
+    """ Add toaster to sys path for importing modules
+    """
+    sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'toaster'))
+_configure_toaster()
+
 from toaster.orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
 from toaster.orm.models import Target_Image_File, BuildArtifact
 from toaster.orm.models import Variable, VariableHistory
@@ -33,14 +41,17 @@ from toaster.orm.models import Task_Dependency, Package_Dependency
 from toaster.orm.models import Recipe_Dependency
 
 from toaster.orm.models import Project
+from bldcontrol.models import BuildEnvironment, BuildRequest
 
-from bb.msg import BBLogFormatter as format
+from bb.msg import BBLogFormatter as formatter
 from django.db import models
 from pprint import pformat
 import logging
 
 from django.db import transaction, connection
 
+# pylint: disable=invalid-name
+# the logger name is standard throughout BitBake
 logger = logging.getLogger("ToasterLogger")
 
 
@@ -57,7 +68,6 @@ class ORMWrapper(object):
         self.layer_version_objects = []
         self.task_objects = {}
         self.recipe_objects = {}
-        pass
 
     @staticmethod
     def _build_key(**kwargs):
@@ -106,6 +116,13 @@ class ORMWrapper(object):
 
         return vars(self)[dictname][key]
 
+    # pylint: disable=no-self-use
+    # we disable detection of no self use in functions because the methods actually work on the object
+    # even if they don't touch self anywhere
+
+    # pylint: disable=bad-continuation
+    # we do not follow the python conventions for continuation indentation due to long lines here
+
     def create_build_object(self, build_info, brbe, project_id):
         assert 'machine' in build_info
         assert 'distro' in build_info
@@ -119,8 +136,7 @@ class ORMWrapper(object):
         buildrequest = None
         if brbe is not None:            # this build was triggered by a request from a user
             logger.debug(1, "buildinfohelper: brbe is %s" % brbe)
-            from bldcontrol.models import BuildEnvironment, BuildRequest
-            br, be = brbe.split(":")
+            br, _ = brbe.split(":")
             buildrequest = BuildRequest.objects.get(pk = br)
             prj = buildrequest.project
 
@@ -129,18 +145,16 @@ class ORMWrapper(object):
             prj = Project.objects.get(pk = project_id)
 
         else:                           # this build was triggered by a legacy system, or command line interactive mode
-            prj, created = Project.objects.get_or_create(pk=0, name="Default Project")
+            prj, _ = Project.objects.get_or_create(pk=0, name="Default Project")
             logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj)
 
 
         if buildrequest is not None:
             build = buildrequest.build
-            logger.info("Updating existing build, with %s" % build_info)
+            logger.info("Updating existing build, with %s", build_info)
             build.machine=build_info['machine']
             build.distro=build_info['distro']
             build.distro_version=build_info['distro_version']
-            started_on=build_info['started_on']
-            completed_on=build_info['started_on']
             build.cooker_log_path=build_info['cooker_log_path']
             build.build_name=build_info['build_name']
             build.bitbake_version=build_info['bitbake_version']
@@ -210,8 +224,8 @@ class ORMWrapper(object):
                         task_name=task_information['task_name']
                         )
         if created and must_exist:
-                task_information['debug'] = "build id %d, recipe id %d" % (task_information['build'].pk, task_information['recipe'].pk)
-                raise NotExisting("Task object created when expected to exist", task_information)
+            task_information['debug'] = "build id %d, recipe id %d" % (task_information['build'].pk, task_information['recipe'].pk)
+            raise NotExisting("Task object created when expected to exist", task_information)
 
         object_changed = False
         for v in vars(task_object):
@@ -278,7 +292,7 @@ class ORMWrapper(object):
         assert 'priority' in layer_version_information
         assert 'local_path' in layer_version_information
 
-        layer_version_object, created = Layer_Version.objects.get_or_create(
+        layer_version_object, _ = Layer_Version.objects.get_or_create(
                                     build = build_obj,
                                     layer = layer_obj,
                                     branch = layer_version_information['branch'],
@@ -296,13 +310,12 @@ class ORMWrapper(object):
         assert 'layer_index_url' in layer_information
 
         if brbe is None:
-            layer_object, created = Layer.objects.get_or_create(
+            layer_object, _ = Layer.objects.get_or_create(
                                 name=layer_information['name'],
                                 layer_index_url=layer_information['layer_index_url'])
             return layer_object
         else:
             # we are under managed mode; we must match the layer used in the Project Layer
-            from bldcontrol.models import BuildEnvironment, BuildRequest
             br_id, be_id = brbe.split(":")
 
             # find layer by checkout path;
@@ -422,7 +435,7 @@ class ORMWrapper(object):
 
             try:
                 filetarget_obj = Target_File.objects.get(target = target_obj, path = filetarget_path)
-            except Exception as e:
+            except Target_File.DoesNotExist:
                 # we might have an invalid link; no way to detect this. just set it to None
                 filetarget_obj = None
 
@@ -498,11 +511,11 @@ class ORMWrapper(object):
         if len(packagedeps_objs) > 0:
             Package_Dependency.objects.bulk_create(packagedeps_objs)
 
-        if (len(errormsg) > 0):
-            logger.warn("buildinfohelper: target_package_info could not identify recipes: \n%s" % errormsg)
+        if len(errormsg) > 0:
+            logger.warn("buildinfohelper: target_package_info could not identify recipes: \n%s", errormsg)
 
     def save_target_image_file_information(self, target_obj, file_name, file_size):
-        target_image_file = Target_Image_File.objects.create( target = target_obj,
+        Target_Image_File.objects.create( target = target_obj,
                             file_name = file_name,
                             file_size = file_size)
 
@@ -542,7 +555,7 @@ class ORMWrapper(object):
         if 'OPKGN' in package_info.keys():
             pname = package_info['OPKGN']
 
-        bp_object, created = Package.objects.get_or_create( build = build_obj,
+        bp_object, _ = Package.objects.get_or_create( build = build_obj,
                                        name = pname )
 
         bp_object.installed_name = package_info['PKG']
@@ -559,7 +572,7 @@ class ORMWrapper(object):
         # save any attached file information
         packagefile_objects = []
         for path in package_info['FILES_INFO']:
-                packagefile_objects.append(Package_File( package = bp_object,
+            packagefile_objects.append(Package_File( package = bp_object,
                                         path = path,
                                         size = package_info['FILES_INFO'][path] ))
         if len(packagefile_objects):
@@ -643,7 +656,19 @@ class ORMWrapper(object):
 
         HelpText.objects.bulk_create(helptext_objects)
 
-class MockEvent: pass           # sometimes we mock an event, declare it here
+
+class MockEvent(object):
+    """ This object is used to create event, for which normal event-processing methods can
+        be used, out of data that is not coming via an actual event
+    """
+    def __init__(self):
+        self.msg = None
+        self.levelno = None
+        self.taskname = None
+        self.taskhash = None
+        self.pathname = None
+        self.lineno = None
+
 
 class BuildInfoHelper(object):
     """ This class gathers the build information from the server and sends it
@@ -652,9 +677,12 @@ class BuildInfoHelper(object):
         Keeps in memory all data that needs matching before writing it to the database
     """
 
+    # pylint: disable=protected-access
+    # the code will look into the protected variables of the event; no easy way around this
+    # pylint: disable=bad-continuation
+    # we do not follow the python conventions for continuation indentation due to long lines here
 
     def __init__(self, server, has_build_history = False):
-        self._configure_django()
         self.internal_state = {}
         self.internal_state['taskdata'] = {}
         self.task_order = 0
@@ -671,10 +699,6 @@ class BuildInfoHelper(object):
         logger.debug(1, "buildinfohelper: Build info helper inited %s" % vars(self))
 
 
-    def _configure_django(self):
-        # Add toaster to sys path for importing modules
-        sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'toaster'))
-
     ###################
     ## methods to convert event/external info into objects that the ORM layer uses
 
@@ -727,7 +751,6 @@ class BuildInfoHelper(object):
         else:
             br_id, be_id = self.brbe.split(":")
             from bldcontrol.bbcontroller import getBuildEnvironmentController
-            from bldcontrol.models import BuildRequest
             bc = getBuildEnvironmentController(pk = be_id)
 
             def _slkey_managed(layer_version):
@@ -747,11 +770,11 @@ class BuildInfoHelper(object):
                             return lvo
 
         #if we get here, we didn't read layers correctly; dump whatever information we have on the error log
-        logger.warn("Could not match layer version for recipe path %s : %s" % (path, self.orm_wrapper.layer_version_objects))
+        logger.warn("Could not match layer version for recipe path %s : %s", path, self.orm_wrapper.layer_version_objects)
 
         #mockup the new layer
-        unknown_layer, created = Layer.objects.get_or_create(name="__FIXME__unidentified_layer", layer_index_url="")
-        unknown_layer_version_obj, created = Layer_Version.objects.get_or_create(layer = unknown_layer, build = self.internal_state['build'])
+        unknown_layer, _ = Layer.objects.get_or_create(name="__FIXME__unidentified_layer", layer_index_url="")
+        unknown_layer_version_obj, _ = Layer_Version.objects.get_or_create(layer = unknown_layer, build = self.internal_state['build'])
 
         # append it so we don't run into this error again and again
         self.orm_wrapper.layer_version_objects.append(unknown_layer_version_obj)
@@ -798,13 +821,6 @@ class BuildInfoHelper(object):
 
         return build_stats_path
 
-    def _remove_redundant(self, string):
-        ret = []
-        for i in string.split():
-            if i not in ret:
-                ret.append(i)
-        return " ".join(sorted(ret))
-
 
     ################################
     ## external available methods to store information
@@ -827,7 +843,7 @@ class BuildInfoHelper(object):
                 self.internal_state['lvs'][self.orm_wrapper.get_update_layer_object(layerinfos[layer], self.brbe)] = layerinfos[layer]['version']
                 self.internal_state['lvs'][self.orm_wrapper.get_update_layer_object(layerinfos[layer], self.brbe)]['local_path'] = layerinfos[layer]['local_path']
             except NotExisting as nee:
-                logger.warn("buildinfohelper: cannot identify layer exception:%s " % nee)
+                logger.warn("buildinfohelper: cannot identify layer exception:%s ", nee)
 
 
     def store_started_build(self, event):
@@ -861,8 +877,7 @@ class BuildInfoHelper(object):
         path_prefixes = []
 
         if self.brbe is not None:
-            br_id, be_id = self.brbe.split(":")
-            from bldcontrol.models import BuildEnvironment, BuildRequest
+            _, be_id = self.brbe.split(":")
             be = BuildEnvironment.objects.get(pk = be_id)
             path_prefixes.append(be.builddir)
 
@@ -887,7 +902,6 @@ class BuildInfoHelper(object):
 
 
     def update_target_image_file(self, event):
-        image_fstypes = self.server.runCommand(["getVariable", "IMAGE_FSTYPES"])[0]
         evdata = BuildInfoHelper._get_data_from_event(event)
 
         for t in self.internal_state['targets']:
@@ -949,7 +963,7 @@ class BuildInfoHelper(object):
             self.task_order += 1
             task_information['order'] = self.task_order
 
-        task_obj = self.orm_wrapper.get_update_task_object(task_information)
+        self.orm_wrapper.get_update_task_object(task_information)
 
         self.internal_state['taskdata'][identifier] = {
                         'outcome': task_information['outcome'],
@@ -970,7 +984,7 @@ class BuildInfoHelper(object):
                             file_path__endswith = recipe_information['file_path'],
                             name = recipename)
             except Recipe.DoesNotExist:
-                logger.error("Could not find recipe for recipe_information %s name %s" % (pformat(recipe_information), recipename))
+                logger.error("Could not find recipe for recipe_information %s name %s" , pformat(recipe_information), recipename)
                 raise
 
             task_information = {}
@@ -981,7 +995,7 @@ class BuildInfoHelper(object):
             task_information['disk_io'] = taskstats['disk_io']
             if 'elapsed_time' in taskstats:
                 task_information['elapsed_time'] = taskstats['elapsed_time']
-            task_obj = self.orm_wrapper.get_update_task_object(task_information, True)  # must exist
+            self.orm_wrapper.get_update_task_object(task_information, True)  # must exist
 
     def update_and_store_task(self, event):
         assert 'taskfile' in vars(event)
@@ -1047,7 +1061,7 @@ class BuildInfoHelper(object):
     def store_missed_state_tasks(self, event):
         for (fn, taskname, taskhash, sstatefile) in BuildInfoHelper._get_data_from_event(event)['missed']:
 
-            identifier = fn + taskname + "_setscene"
+            # identifier = fn + taskname + "_setscene"
             recipe_information = self._get_recipe_information_from_taskfile(fn)
             recipe = self.orm_wrapper.get_update_recipe_object(recipe_information)
             mevent = MockEvent()
@@ -1065,7 +1079,7 @@ class BuildInfoHelper(object):
 
         for (fn, taskname, taskhash, sstatefile) in BuildInfoHelper._get_data_from_event(event)['found']:
 
-            identifier = fn + taskname + "_setscene"
+            # identifier = fn + taskname + "_setscene"
             recipe_information = self._get_recipe_information_from_taskfile(fn)
             recipe = self.orm_wrapper.get_update_recipe_object(recipe_information)
             mevent = MockEvent()
@@ -1105,7 +1119,7 @@ class BuildInfoHelper(object):
         # save layer version priorities
         if 'layer-priorities' in event._depgraph.keys():
             for lv in event._depgraph['layer-priorities']:
-                (name, path, regexp, priority) = lv
+                (_, path, _, priority) = lv
                 layer_version_obj = self._get_layer_version_for_path(path[1:]) # paths start with a ^
                 assert layer_version_obj is not None
                 layer_version_obj.priority = priority
@@ -1218,8 +1232,8 @@ class BuildInfoHelper(object):
                 taskdeps_objects.append(Task_Dependency( task = target, depends_on = dep ))
         Task_Dependency.objects.bulk_create(taskdeps_objects)
 
-        if (len(errormsg) > 0):
-            logger.warn("buildinfohelper: dependency info not identify recipes: \n%s" % errormsg)
+        if len(errormsg) > 0:
+            logger.warn("buildinfohelper: dependency info not identify recipes: \n%s", errormsg)
 
 
     def store_build_package_information(self, event):
@@ -1232,7 +1246,6 @@ class BuildInfoHelper(object):
     def _store_build_done(self, errorcode):
         logger.info("Build exited with errorcode %d", errorcode)
         br_id, be_id = self.brbe.split(":")
-        from bldcontrol.models import BuildEnvironment, BuildRequest
         be = BuildEnvironment.objects.get(pk = be_id)
         be.lock = BuildEnvironment.LOCK_LOCK
         be.save()
@@ -1247,7 +1260,7 @@ class BuildInfoHelper(object):
 
     def store_log_error(self, text):
         mockevent = MockEvent()
-        mockevent.levelno = format.ERROR
+        mockevent.levelno = formatter.ERROR
         mockevent.msg = text
         mockevent.pathname = '-- None'
         mockevent.lineno = LogMessage.ERROR
@@ -1263,7 +1276,7 @@ class BuildInfoHelper(object):
 
 
     def store_log_event(self, event):
-        if event.levelno < format.WARNING:
+        if event.levelno < formatter.WARNING:
             return
 
         if 'args' in vars(event):
@@ -1276,8 +1289,7 @@ class BuildInfoHelper(object):
                 self.internal_state['backlog'].append(event)
                 return
             else:   # we're under Toaster control, the build is already created
-                from bldcontrol.models import BuildRequest, BRError
-                br, be = self.brbe.split(":")
+                br, _ = self.brbe.split(":")
                 buildrequest = BuildRequest.objects.get(pk = br)
                 self.internal_state['build'] = buildrequest.build
 
@@ -1293,9 +1305,9 @@ class BuildInfoHelper(object):
 
         log_information = {}
         log_information['build'] = self.internal_state['build']
-        if event.levelno == format.ERROR:
+        if event.levelno == formatter.ERROR:
             log_information['level'] = LogMessage.ERROR
-        elif event.levelno == format.WARNING:
+        elif event.levelno == formatter.WARNING:
             log_information['level'] = LogMessage.WARNING
         elif event.levelno == -2:   # toaster self-logging
             log_information['level'] = -2
@@ -1305,7 +1317,7 @@ class BuildInfoHelper(object):
         log_information['message'] = event.msg
         log_information['pathname'] = event.pathname
         log_information['lineno'] = event.lineno
-        logger.info("Logging error 2: %s" % log_information)
+        logger.info("Logging error 2: %s", log_information)
         self.orm_wrapper.create_logmessage(log_information)
 
     def close(self, errorcode):
@@ -1320,7 +1332,7 @@ class BuildInfoHelper(object):
             else:
                 # we have no build, and we still have events; something amazingly wrong happend
                 for event in self.internal_state['backlog']:
-                   logger.error("UNSAVED log: %s", event.msg)
+                    logger.error("UNSAVED log: %s", event.msg)
 
         if not connection.features.autocommits_when_autocommit_is_off:
             transaction.set_autocommit(True)
diff --git a/lib/bb/ui/toasterui.py b/lib/bb/ui/toasterui.py
index 767bfab..9c7e87d 100644
--- a/lib/bb/ui/toasterui.py
+++ b/lib/bb/ui/toasterui.py
@@ -31,16 +31,12 @@ from bb.ui import uihelper
 from bb.ui.buildinfohelper import BuildInfoHelper
 
 import bb.msg
-import copy
-import fcntl
 import logging
 import os
-import progressbar
-import signal
-import struct
-import sys
-import time
-import xmlrpclib
+
+# pylint: disable=invalid-name
+# module properties for UI modules are read by bitbake and the contract should not be broken
+
 
 featureSet = [bb.cooker.CookerFeatures.HOB_EXTRA_CACHES, bb.cooker.CookerFeatures.SEND_DEPENDS_TREE, bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING, bb.cooker.CookerFeatures.SEND_SANITYEVENTS]
 
@@ -53,15 +49,15 @@ def _log_settings_from_server(server):
     # Get values of variables which control our output
     includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
     if error:
-        logger.error("Unable to get the value of BBINCLUDELOGS variable: %s" % error)
+        logger.error("Unable to get the value of BBINCLUDELOGS variable: %s", error)
         raise BaseException(error)
     loglines, error = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
     if error:
-        logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s" % error)
+        logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s", error)
         raise BaseException(error)
     consolelogfile, error = server.runCommand(["getVariable", "BB_CONSOLELOG"])
     if error:
-        logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
+        logger.error("Unable to get the value of BB_CONSOLELOG variable: %s", error)
         raise BaseException(error)
     return includelogs, loglines, consolelogfile
 
@@ -71,17 +67,17 @@ def main(server, eventHandler, params ):
 
     console = logging.StreamHandler(sys.stdout)
     format_str = "%(levelname)s: %(message)s"
-    format = bb.msg.BBLogFormatter(format_str)
+    formatter = bb.msg.BBLogFormatter(format_str)
     bb.msg.addDefaultlogFilter(console)
-    console.setFormatter(format)
+    console.setFormatter(formatter)
     logger.addHandler(console)
     logger.setLevel(logging.INFO)
 
-    includelogs, loglines, consolelogfile = _log_settings_from_server(server)
+    _, _, consolelogfile = _log_settings_from_server(server)
 
     # verify and warn
     build_history_enabled = True
-    inheritlist, error = server.runCommand(["getVariable", "INHERIT"])
+    inheritlist, _ = server.runCommand(["getVariable", "INHERIT"])
 
     if not "buildhistory" in inheritlist.split(" "):
         logger.warn("buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details.")
@@ -126,12 +122,15 @@ def main(server, eventHandler, params ):
 
             helper.eventHandler(event)
 
+            # pylint: disable=protected-access
+            # the code will look into the protected variables of the event; no easy way around this
+
             if isinstance(event, bb.event.BuildStarted):
                 buildinfohelper.store_started_build(event)
 
             if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded, bb.build.TaskFailedSilent)):
                 buildinfohelper.update_and_store_task(event)
-                logger.warn("Logfile for task %s" % event.logfile)
+                logger.warn("Logfile for task %s", event.logfile)
                 continue
 
             if isinstance(event, bb.build.TaskBase):
@@ -143,17 +142,17 @@ def main(server, eventHandler, params ):
 
             if isinstance(event, logging.LogRecord):
                 if event.levelno == -1:
-                    event.levelno = format.ERROR
+                    event.levelno = formatter.ERROR
 
                 buildinfohelper.store_log_event(event)
-                if event.levelno >= format.ERROR:
+                if event.levelno >= formatter.ERROR:
                     errors = errors + 1
-                elif event.levelno == format.WARNING:
+                elif event.levelno == formatter.WARNING:
                     warnings = warnings + 1
                 # For "normal" logging conditions, don't show note logs from tasks
                 # but do show them if the user has changed the default log level to
                 # include verbose/debug messages
-                if event.taskpid != 0 and event.levelno <= format.NOTE:
+                if event.taskpid != 0 and event.levelno <= formatter.NOTE:
                     continue
 
                 logger.handle(event)
@@ -241,8 +240,8 @@ def main(server, eventHandler, params ):
 
             if isinstance(event, (bb.event.BuildCompleted, bb.command.CommandFailed)):
 
-		errorcode = 0
-                if (isinstance(event, bb.command.CommandFailed)):
+                errorcode = 0
+                if isinstance(event, bb.command.CommandFailed):
                     errors += 1
                     errorcode = 1
                     logger.error("Command execution failed: %s", event.error)
@@ -251,7 +250,7 @@ def main(server, eventHandler, params ):
                 buildinfohelper.update_build_information(event, errors, warnings, taskfailures)
                 buildinfohelper.close(errorcode)
                 # mark the log output; controllers may kill the toasterUI after seeing this log
-                logger.info("ToasterUI build done 1, brbe: %s" % buildinfohelper.brbe )
+                logger.info("ToasterUI build done 1, brbe: %s", buildinfohelper.brbe )
 
                 # we start a new build info
                 if buildinfohelper.brbe is not None:
@@ -293,7 +292,7 @@ def main(server, eventHandler, params ):
                 elif event.type == "LicenseManifestPath":
                     buildinfohelper.store_license_manifest_path(event)
                 else:
-                    logger.error("Unprocessed MetadataEvent %s " % str(event))
+                    logger.error("Unprocessed MetadataEvent %s ", str(event))
                 continue
 
             if isinstance(event, bb.cooker.CookerExit):
@@ -325,30 +324,28 @@ def main(server, eventHandler, params ):
                 pass
         except KeyboardInterrupt:
             main.shutdown = 1
-            pass
         except Exception as e:
             # print errors to log
             import traceback
             from pprint import pformat
             exception_data = traceback.format_exc()
-            logger.error("%s\n%s" % (e, exception_data))
+            logger.error("%s\n%s" , e, exception_data)
 
-            exc_type, exc_value, tb = sys.exc_info()
+            _, _, tb = sys.exc_info()
             if tb is not None:
                 curr = tb
                 while curr is not None:
-                    logger.warn("Error data dump %s\n%s\n" % (traceback.format_tb(curr,1), pformat(curr.tb_frame.f_locals)))
+                    logger.warn("Error data dump %s\n%s\n" , traceback.format_tb(curr,1), pformat(curr.tb_frame.f_locals))
                     curr = curr.tb_next
 
             # save them to database, if possible; if it fails, we already logged to console.
             try:
                 buildinfohelper.store_log_exception("%s\n%s" % (str(e), exception_data))
             except Exception as ce:
-                logger.error("CRITICAL - Failed to to save toaster exception to the database: %s" % str(ce))
+                logger.error("CRITICAL - Failed to to save toaster exception to the database: %s", str(ce))
 
             # make sure we return with an error
             return_value += 1
-            pass
 
     if interrupted:
         if return_value == 0:
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 13/14] toastergui: do not show in-progress builds in the table
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (11 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 12/14] bitbake: toaster logger: fix pylint issues Michael Wood
@ 2015-08-18 16:28 ` Michael Wood
  2015-08-18 16:29 ` [PATCH 14/14] toastergui: fix projectbuilds page Michael Wood
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:28 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

This patch fixes the all-builds table as not to show
in-progress builds.

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 lib/toaster/toastergui/views.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 20f7cb3..086d387 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -1892,7 +1892,7 @@ if True:
         # be able to display something.  'count' and 'page' are mandatory for all views
         # that use paginators.
 
-        queryset = Build.objects.filter(outcome__lte = Build.IN_PROGRESS)
+        queryset = Build.objects.exclude(outcome = Build.IN_PROGRESS)
 
         context, pagesize, orderby = _build_list_helper(request, queryset)
 
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 14/14] toastergui: fix projectbuilds page
  2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
                   ` (12 preceding siblings ...)
  2015-08-18 16:28 ` [PATCH 13/14] toastergui: do not show in-progress builds in the table Michael Wood
@ 2015-08-18 16:29 ` Michael Wood
  13 siblings, 0 replies; 17+ messages in thread
From: Michael Wood @ 2015-08-18 16:29 UTC (permalink / raw)
  To: bitbake-devel

From: Alexandru DAMIAN <alexandru.damian@intel.com>

This patch fixes the redirection projectbuilds page and
the template layout in the projectbuilds page.

* The _build_list_helper now returns an empty RedirectException
that is properly customized by the caller and re-raised
to achieve redirection to the original page (poor man's overloading)

* The template for ProjectBuilds is updated as to properly display
Build objects instead of BuildRequest objects.

[YOCTO #7995]

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 .../toastergui/templates/projectbuilds.html        | 42 +++-------------------
 lib/toaster/toastergui/views.py                    | 24 +++++++++----
 2 files changed, 21 insertions(+), 45 deletions(-)

diff --git a/lib/toaster/toastergui/templates/projectbuilds.html b/lib/toaster/toastergui/templates/projectbuilds.html
index 646755b..f1db2f1 100644
--- a/lib/toaster/toastergui/templates/projectbuilds.html
+++ b/lib/toaster/toastergui/templates/projectbuilds.html
@@ -16,8 +16,8 @@
 <script>
     // initialize the date range controls
     $(document).ready(function () {
-        date_init('created','{{last_date_from}}','{{last_date_to}}','{{dateMin_created}}','{{dateMax_created}}','{{daterange_selected}}');
-        date_init('updated','{{last_date_from}}','{{last_date_to}}','{{dateMin_updated}}','{{dateMax_updated}}','{{daterange_selected}}');
+        date_init('created','{{last_date_from}}','{{last_date_to}}','{{dateMin_started_on}}','{{dateMax_started_on}}','{{daterange_selected}}');
+        date_init('updated','{{last_date_from}}','{{last_date_to}}','{{dateMin_completed_on}}','{{dateMax_completed_on}}','{{daterange_selected}}');
     });
 </script>
 
@@ -28,7 +28,7 @@
         {%elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
             No builds found
         {%else%}
-            All builds
+            Project builds
         {%endif%}
         <i class="icon-question-sign get-help heading-help" title="This page lists all the builds for the current project"></i>
       </h1>
@@ -58,7 +58,7 @@
 
   {% include "basetable_top.html" %}
         <!-- Table data rows; the order needs to match the order of "tablecols" definitions; and the <td class value needs to match the tablecols clclass value for show/hide buttons to work -->
-        {% for br in objects %}{% if br.build %}  {% with build=br.build %} {# if we have a build, just display it #}
+        {% for build in objects %} {# if we have a build, just display it #}
         <tr class="data">
             <td class="outcome"><a href="{% url "builddashboard" build.id %}">{%if build.outcome == build.SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif build.outcome == build.FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%}</a>
                    {% if build.project %}
@@ -96,40 +96,6 @@
               {% endif %}
             </td>
         </tr>
-
-              {%endwith%}
-      {% else %} {# we don't have a build for this build request, mask the data with build request data #}
-
-
-
-        <tr class="data">
-            <td class="outcome">{% if br.state == br.REQ_FAILED %}<i class="icon-minus-sign error"></i>{%else%}FIXME_build_request_state{%endif%}</td>
-            <td class="target">
-                <a href="{% url "builddashboard" br.id %}"><span data-toggle="tooltip" {%if br.brtarget_set.all.count > 1%}title="Targets: {%for target in br.brtarget_set.all%}{{target.target}} {%endfor%}"{%endif%}>{{br.brtarget_set.all.0.target}} {%if br.brtarget_set.all.count > 1%}(+ {{br.brtarget_set.all.count|add:"-1"}}){%endif%} </span></a>
-            </td>
-            <td class="machine">
-                <a href="{% url "builddashboard" br.id %}">{{br.machine}}</a>
-            </td>
-            <td class="started_on">
-                <a href="{% url "builddashboard" br.id %}">{{br.created|date:"d/m/y H:i"}}</a>
-            </td>
-            <td class="completed_on">
-                <a href="{% url "builddashboard" br.id %}">{{br.updated|date:"d/m/y H:i"}}</a>
-            </td>
-            <td class="failed_tasks error">
-            </td>
-            <td class="errors.count">
-        <a class="errors.count error" href="{% url "builddashboard" br.id %}#errors">{{br.brerror_set.all.count}} error{{br.brerror_set.all.count|pluralize}}</a>
-            </td>
-            <td class="warnings.count">
-            </td>
-            <td class="time">
-                {{br.timespent.total_seconds|sectohms}}
-            </td>
-            <td class="output"> {# we have no output here #}
-            </td>
-        </tr>
-          {%endif%}
         {% endfor %}
 
 
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 086d387..7641f86 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -33,7 +33,7 @@ from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File
 from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact
 from bldcontrol import bbcontroller
 from django.views.decorators.cache import cache_control
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, resolve
 from django.core.exceptions import MultipleObjectsReturned
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 from django.http import HttpResponseBadRequest, HttpResponseNotFound
@@ -372,7 +372,6 @@ def _get_queryset(model, queryset, filter_string, search_term, ordering_string,
 # if the value is given explicitly as a GET parameter it will be the first selected,
 # otherwise the cookie value will be used.
 def _get_parameters_values(request, default_count, default_order):
-    from django.core.urlresolvers import resolve
     current_url = resolve(request.path_info).url_name
     pagesize = request.GET.get('count', request.session.get('%s_count' % current_url, default_count))
     orderby = request.GET.get('orderby', request.session.get('%s_orderby' % current_url, default_order))
@@ -1894,7 +1893,14 @@ if True:
 
         queryset = Build.objects.exclude(outcome = Build.IN_PROGRESS)
 
-        context, pagesize, orderby = _build_list_helper(request, queryset)
+        try:
+            context, pagesize, orderby = _build_list_helper(request, queryset)
+            # all builds page as a Project column
+            context['tablecols'].append({'name': 'Project', 'clcalss': 'project_column', })
+        except RedirectException as re:
+            # rewrite the RedirectException
+            re.view = resolve(request.path_info).url_name
+            raise re
 
         _set_parameters_values(pagesize, orderby, request)
         return context
@@ -1908,7 +1914,7 @@ if True:
         mandatory_parameters = { 'count': pagesize,  'page' : 1, 'orderby' : orderby }
         retval = _verify_parameters( request.GET, mandatory_parameters )
         if retval:
-            raise RedirectException( 'all-builds', request.GET, mandatory_parameters)
+            raise RedirectException( None, request.GET, mandatory_parameters)
 
         # boilerplate code that takes a request for an object type and returns a queryset
         # for that object type. copypasta for all needed table searches
@@ -2083,8 +2089,6 @@ if True:
                     {'name': 'Image files', 'clclass': 'output',
                      'qhelp': "The root file system types produced by the build. You can find them in your <code>/build/tmp/deploy/images/</code> directory",
                         # TODO: compute image fstypes from Target_Image_File
-                    },
-                    {'name': 'Project', 'clcalss': 'project_column',
                     }
                     ]
                 }
@@ -2655,7 +2659,13 @@ if True:
 
         queryset = Build.objects.filter(outcome__lte = Build.IN_PROGRESS)
 
-        context, pagesize, orderby = _build_list_helper(request, queryset)
+        try:
+            context, pagesize, orderby = _build_list_helper(request, queryset)
+        except RedirectException as re:
+            # rewrite the RedirectException with our current url information
+            re.view = resolve(request.path_info).url_name
+            re.okwargs = {"pid" : pid}
+            raise re
 
         context['project'] = prj
         _set_parameters_values(pagesize, orderby, request)
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 12/14] bitbake: toaster logger: fix pylint issues
  2015-08-18 16:28 ` [PATCH 12/14] bitbake: toaster logger: fix pylint issues Michael Wood
@ 2015-08-20 12:55   ` Olof Johansson
  2015-08-20 21:06     ` Richard Purdie
  0 siblings, 1 reply; 17+ messages in thread
From: Olof Johansson @ 2015-08-20 12:55 UTC (permalink / raw)
  To: Michael Wood, bitbake-devel

Excerpts from Michael Wood's message of 2015-08-18 18:28:58 +0200:
> From: Alexandru DAMIAN <alexandru.damian@intel.com>
> 
> This patch fixes pylint issues in the toaster build data logger,
> toasterui. The following types of warnings are touched here:
> 
> * fixing imports
> * unused variables are set to _
> * logger calls now use lazy evaluation instead of formatting
> the string
> * correct whitespace identation
> * removes unneeded "pass" statements, and extra parantheses
> * disable specific pylint warnings when decideing to override
> them

This change causes the following RuntimeError exception, when running bitbake
(any bitbake command):

$ python --version
Python 2.7.9
$ bitbake
Traceback (most recent call last):
  File ".../poky/bitbake/bin/bitbake", line 44, in <module>
    sys.exit(bitbake_main(BitBakeConfigParameters(sys.argv),
  File ".../poky/bitbake/lib/bb/cookerdata.py", line 37, in __init__
    self.options, targets = self.parseCommandLine(argv)
  File ".../poky/bitbake/lib/bb/main.py", line 178, in parseCommandLine
    valid_uis = list_extension_modules(bb.ui, 'main')
  File ".../poky/bitbake/lib/bb/main.py", line 62, in list_extension_modules
    module = __import__(pkg.__name__, fromlist=[modulename])
  File ".../poky/bitbake/lib/bb/ui/buildinfohelper.py", line 44, in <module>
    from bldcontrol.models import BuildEnvironment, BuildRequest
  File ".../poky/bitbake/lib/toaster/bldcontrol/models.py", line 3, in <module>
    from orm.models import Project, ProjectLayer, ProjectVariable, ProjectTarget, Build
  File ".../poky/bitbake/lib/toaster/orm/models.py", line 56, in <module>
    class ToasterSetting(models.Model):
  File "/usr/lib/python2.7/dist-packages/django/db/models/base.py", line 283, in __new__
    new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
  File "/usr/lib/python2.7/dist-packages/django/apps/registry.py", line 221, in register_model
    (model_name, app_label, app_models[model_name], model))
RuntimeError: Conflicting 'toastersetting' models in application 'orm': <class 'toaster.orm.models.ToasterSetting'> and <class 'orm.models.ToasterSetting'>.

Even though .../poky/bitbake/lib is already in the sys.path,
.../poky/bitbake/lib/toaster is also added, which seem to be the cause of this
issue.

I'm a bit surprised that this kind of change causes issues for use of bitbake
not related to toaster.

-- 
olof johansson


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 12/14] bitbake: toaster logger: fix pylint issues
  2015-08-20 12:55   ` Olof Johansson
@ 2015-08-20 21:06     ` Richard Purdie
  0 siblings, 0 replies; 17+ messages in thread
From: Richard Purdie @ 2015-08-20 21:06 UTC (permalink / raw)
  To: Olof Johansson, Eggleton, Paul; +Cc: bitbake-devel

On Thu, 2015-08-20 at 14:55 +0200, Olof Johansson wrote:
> Excerpts from Michael Wood's message of 2015-08-18 18:28:58 +0200:
> > From: Alexandru DAMIAN <alexandru.damian@intel.com>
> > 
> > This patch fixes pylint issues in the toaster build data logger,
> > toasterui. The following types of warnings are touched here:
> > 
> > * fixing imports
> > * unused variables are set to _
> > * logger calls now use lazy evaluation instead of formatting
> > the string
> > * correct whitespace identation
> > * removes unneeded "pass" statements, and extra parantheses
> > * disable specific pylint warnings when decideing to override
> > them
> 
> This change causes the following RuntimeError exception, when running bitbake
> (any bitbake command):
> 
> $ python --version
> Python 2.7.9
> $ bitbake
> Traceback (most recent call last):
>   File ".../poky/bitbake/bin/bitbake", line 44, in <module>
>     sys.exit(bitbake_main(BitBakeConfigParameters(sys.argv),
>   File ".../poky/bitbake/lib/bb/cookerdata.py", line 37, in __init__
>     self.options, targets = self.parseCommandLine(argv)
>   File ".../poky/bitbake/lib/bb/main.py", line 178, in parseCommandLine
>     valid_uis = list_extension_modules(bb.ui, 'main')
>   File ".../poky/bitbake/lib/bb/main.py", line 62, in list_extension_modules
>     module = __import__(pkg.__name__, fromlist=[modulename])
>   File ".../poky/bitbake/lib/bb/ui/buildinfohelper.py", line 44, in <module>
>     from bldcontrol.models import BuildEnvironment, BuildRequest
>   File ".../poky/bitbake/lib/toaster/bldcontrol/models.py", line 3, in <module>
>     from orm.models import Project, ProjectLayer, ProjectVariable, ProjectTarget, Build
>   File ".../poky/bitbake/lib/toaster/orm/models.py", line 56, in <module>
>     class ToasterSetting(models.Model):
>   File "/usr/lib/python2.7/dist-packages/django/db/models/base.py", line 283, in __new__
>     new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
>   File "/usr/lib/python2.7/dist-packages/django/apps/registry.py", line 221, in register_model
>     (model_name, app_label, app_models[model_name], model))
> RuntimeError: Conflicting 'toastersetting' models in application 'orm': <class 'toaster.orm.models.ToasterSetting'> and <class 'orm.models.ToasterSetting'>.
> 
> Even though .../poky/bitbake/lib is already in the sys.path,
> .../poky/bitbake/lib/toaster is also added, which seem to be the cause of this
> issue.
> 
> I'm a bit surprised that this kind of change causes issues for use of bitbake
> not related to toaster.

We're all a bit surprised. Its a nasty effect of Pauls recent "list all
the modules in bitbake --help" change :(.

Randy's sent I patch I've merged which at least bandaids this issue...

Cheers,

Richard



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-08-20 21:06 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-18 16:28 [PATCH 00/14] Toaster patches Michael Wood
2015-08-18 16:28 ` [PATCH 01/14] bitbake: toaster: pylint fixes Michael Wood
2015-08-18 16:28 ` [PATCH 02/14] bitbake: toaster: checksettings: fix guesspath initialization Michael Wood
2015-08-18 16:28 ` [PATCH 03/14] bitbake: toaster: checksettings: fix TEMPLATECONF detection Michael Wood
2015-08-18 16:28 ` [PATCH 04/14] bitbake: toaster: improve exception handling Michael Wood
2015-08-18 16:28 ` [PATCH 05/14] bitbake: toaster: models field initialization Michael Wood
2015-08-18 16:28 ` [PATCH 06/14] bitbake: toaster: use loggers instead of prints Michael Wood
2015-08-18 16:28 ` [PATCH 07/14] bitbake: toastergui: rename variables in views.py Michael Wood
2015-08-18 16:28 ` [PATCH 08/14] bitbake: toaster: do not stop data import on bad data Michael Wood
2015-08-18 16:28 ` [PATCH 09/14] bitbake: toaster: replace raising Exceptions in loadconf Michael Wood
2015-08-18 16:28 ` [PATCH 10/14] bitbake: toaster: fix updates on failed build requests Michael Wood
2015-08-18 16:28 ` [PATCH 11/14] bitbake: toaster: fix pylint errors Michael Wood
2015-08-18 16:28 ` [PATCH 12/14] bitbake: toaster logger: fix pylint issues Michael Wood
2015-08-20 12:55   ` Olof Johansson
2015-08-20 21:06     ` Richard Purdie
2015-08-18 16:28 ` [PATCH 13/14] toastergui: do not show in-progress builds in the table Michael Wood
2015-08-18 16:29 ` [PATCH 14/14] toastergui: fix projectbuilds page Michael Wood

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.