Package integration :: Module quality |
[hide private]
[frames] | no frames]

# Source Code for Module integration.quality

      1  #============================================================================
      2  #Name        : quality.py
      3  #Part of     : Helium
      4
      5  #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
      6  #All rights reserved.
      7  #This component and the accompanying materials are made available
      8  #under the terms of the License "Eclipse Public License v1.0"
      9  #which accompanies this distribution, and is available
     10  #at the URL "http://www.eclipse.org/legal/epl-v10.html".
     11  #
     12  #Initial Contributors:
     13  #Nokia Corporation - initial contribution.
     14  #
     15  #Contributors:
     16  #
     17  #Description:
     18  #===============================================================================
     19
     20  """
     21  Symbian log based analyser.
     22
     23   * Internal export parser
     24   * Duplicate generation parser (relying on abld -what)
     25
     26  Policy validation.
     27  """
     28
     29  import symbian.log
     30  import re
     31  import os
     32  import sys
     33  import csv
     34  import fileutils
     35  import pathaddition.match
     36  import logging
     37
     38  #logging.basicConfig(level=logging.DEBUG)
     39  _logger = logging.getLogger("integration.quality")
     40
     41 -class InternalExportParser(symbian.log.Parser):
     42      """ This class extends the Symbian log parser class and implement
     43          an "abld -what" analyser which detects file generated/exported inside
     44          the source tree.
     45      """
     46 -    def __init__(self, _file):
     47          """The constructor """
     48          symbian.log.Parser.__init__(self, _file)
     49          self.__match_what = re.compile("abld(\.bat)?(\s+.*)*\s+-w(hat)?", re.I)
     50          self.internalexports = {}
     51
     52 -    def task(self, name, _cmd, _dir, content):
     53          """ Analyse task log. """
     54          if self.__match_what.match(_cmd) != None:
     55              for line in content.splitlines():
     56                  if line.startswith(os.path.sep) \
     57                      and not os.path.normpath(line.strip().lower()).startswith(os.path.sep+"epoc32"+os.path.sep) \
     58                      and os.path.splitext(line.strip().lower())[1] != '':
     59                      if name not in self.internalexports:
     60                          self.internalexports[name] = []
     61                      self.internalexports[name].append(line)
     62
     63
     64 -class AbldWhatParser(symbian.log.Parser):
     65      """ This class extends the Symbian log parser class and implement
     66          an "abld -what" analyser which sort the generated files by component.
     67      """
     68 -    def __init__(self, _file):
     69          """The constructor """
     70          symbian.log.Parser.__init__(self, _file)
     71          self.__match_what = re.compile(r"abld(\.bat)?(\s+.*)*\s+-w(hat)?", re.I)
     72          self.__match_cmaker_what = re.compile(r"cmaker(\.cmd)?(\s+.*)*\s+ACTION=what", re.I)
     73          self.files_per_component = {}
     74          self.components_per_file = {}
     75
     76 -    def task(self, name, _cmd, _dir, content):
     77          """ Analyse task log. """
     78          if _cmd != None and self.__match_what.match(_cmd) != None:
     79              for line in content.splitlines():
     80                  line = line.strip()
     81                  if not os.path.normpath(line).startswith(os.path.sep):
     82                      continue
     83                  # component per file
     84                  if line.lower() not in self.components_per_file:
     85                      self.components_per_file[line.lower()] = []
     86                  if name not in self.components_per_file[line.lower()]:
     87                      self.components_per_file[line.lower()].append(name)
     88
     89                  # file per components
     90                  if name not in self.files_per_component:
     91                      self.files_per_component[name] = []
     92                  self.files_per_component[name].append(line)
     93          elif _cmd != None and self.__match_cmaker_what.match(_cmd) != None:
     94              for line in content.splitlines():
     95                  line = line.strip()
     96                  if not line.startswith('"'):
     97                      continue
     98                  if not line.endswith('"'):
     99                      continue
    100                  line = os.path.normpath(line.strip('"')).lower()
    101                  # component per file
    102                  if line not in self.components_per_file:
    103                      self.components_per_file[line] = []
    104                  if name not in self.components_per_file[line]:
    105                      self.components_per_file[line].append(name)
    106
    107                  # file per components
    108                  if name not in self.files_per_component:
    109                      self.files_per_component[name] = []
    110                  self.files_per_component[name].append(line)
    111
    112
    113 -class PolicyValidator(object):
    114      """ Validate policy files on a hierarchy. """
    115 -    def __init__(self, policyfiles=None, csvfile=None, ignoreroot=False):
    116          """The constructor """
    117          if policyfiles is None:
    118              policyfiles = ['distribution.policy.s60']
    119          self._policyfiles = policyfiles
    120          self._ids = None
    121          self._ignoreroot = ignoreroot
    122
    123 -    def load_policy_ids(self, csvfile):
    124          """ Load the icds from the CSV file.
    125              report format by generating array: ['unknownstatus', value, description]
    126          """
    127          self._ids = {}
    128          reader = csv.reader(open(csvfile, "rU"))
    129          for row in reader:
    130              if re.match(r"^\s*\d+\s*$", row[0]):
    131                  self._ids[row[0]] = row
    132                  if row[1].lower() != "yes" and row[1].lower() != "no" and row[1].lower() != "bin":
    133                      yield ["unknownstatus", row[0], row[2]]
    134
    135 -    def validate_content(self, filename):
    136          """  Validating the policy file content. If it cannot be decoded,
    137              it reports an 'invalidencoding'.
    138              Case 'notinidlist': value is not defined under the id list.
    139          """
    140          value = None
    141          try:
    142              value = fileutils.read_policy_content(filename)
    143          except Exception:
    144              yield ["invalidencoding", filename, None]
    145          if value is not None:
    146              if self._ids != None:
    147                  if value not in self._ids:
    148                      yield ["notinidlist", filename, value]
    149
    150 -    def find_policy(self, path):
    151          """ find the policy file under path using filenames under the list. """
    152          for filename in self._policyfiles:
    153              if sys.platform != 'win32':
    154                  for f in os.listdir(path):
    155                      if f.lower() == filename.lower():
    156                          return os.path.join(path, f)
    157              if os.path.exists(os.path.join(path, filename)):
    158                  return os.path.join(path, filename)
    159          return None
    160
    161 -    def validate(self, path):
    162          """ Return a list couple [errortype, location, policy].
    163              errortype: missing, invalidencoding, notinidlist .
    164              missing: location is a directory.
    165              otherwise the doggie policy file.
    166          """
    167          path = os.path.normpath(path)
    168          for dirpath, _, _ in os.walk(path):
    169              # skipping the root
    170              if dirpath == path and self._ignoreroot:
    171                  continue
    172              # skip svn dirs
    173              if pathaddition.match.ant_match(dirpath, "**/.svn/**"):
    174                  continue
    175              # Skipping j2me content. Shouln't this be done differently?
    176              if pathaddition.match.ant_match(dirpath, "**/j2me/**"):
    177                  continue
    178              filename = self.find_policy(dirpath)
    179              if filename != None:
    180                  for result in self.validate_content(filename):
    181                      yield result
    182              else:
    183                  yield ['missing', dirpath, None]
    184