coverage.py revision 804e064dcd02b87e04b9a189422cc14205e8125c
1326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard#!/usr/bin/env python3 2326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 3fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# INTEL CONFIDENTIAL 4fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# Copyright 2013 Intel 5fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# Corporation All Rights Reserved. 6fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# 7fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# The source code contained or described herein and all documents related to 8fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# the source code ("Material") are owned by Intel Corporation or its suppliers 9fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# or licensors. Title to the Material remains with Intel Corporation or its 10fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# suppliers and licensors. The Material contains trade secrets and proprietary 11fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# and confidential information of Intel or its suppliers and licensors. The 12fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# Material is protected by worldwide copyright and trade secret laws and 13fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# treaty provisions. No part of the Material may be used, copied, reproduced, 14fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# modified, published, uploaded, posted, transmitted, distributed, or 15fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# disclosed in any way without Intels prior express written permission. 16fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# 17fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# No license under any patent, copyright, trade secret or other intellectual 18fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# property right is granted to or conferred upon you by disclosure or delivery 19fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# of the Materials, either expressly, by implication, inducement, estoppel or 20fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# otherwise. Any license under such intellectual property rights must be 21fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard# express and approved by Intel in writing. 22fe753d4ba5d5bf3df7b7f4876280b74fc8647285Kevin Rocard 23326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard""" 24326e39e42a801bff4b61655ebc0e3ff759c208ffKevin RocardGenerate a coverage report by parsing parameter framework log. 25326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 26326e39e42a801bff4b61655ebc0e3ff759c208ffKevin RocardThe coverage report contains the: 27326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - domain 28326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - configuration 29326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - rule 30326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard - criterion 31326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardbasic coverage statistics. 32326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard""" 33326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 34326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport xml.dom.minidom 35326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport sys 36326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport re 37326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardimport logging 38326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 39326e39e42a801bff4b61655ebc0e3ff759c208ffKevin RocardFORMAT = '%(levelname)s: %(message)s' 40326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardlogging.basicConfig(stream=sys.stderr, level=logging.WARNING, format=FORMAT) 41326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardlogger = logging.getLogger("Coverage") 42326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 433aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass CustomError(Exception): 44804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard pass 453aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 463aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass ChildError(CustomError): 47804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, parent, child): 48804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.parent = parent 49804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.child = child 503aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 513aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass ChildNotFoundError(ChildError): 52804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 53804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return "Unable to find the child %s in %s" % (self.child, self.parent) 543aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 553aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass DuplicatedChildError(ChildError): 56804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 57804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return "Add existing child %s in %s." % (self.child, self.parent) 58326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 59326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Element(): 60804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Root class for all coverage elements""" 61804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "element" 62326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 63804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, name): 64326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 65804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.parent = None 66804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.children = [] 67326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 68804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.nbUse = 0 69326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 70804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.name = name 71326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 72804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("New element") 73326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 74326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 75804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 76804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return "%s (%s)" % (self.name, self.tag) 77326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 78804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __eq__(self, compared): 79804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return (self.name == compared.name) and (self.children == compared.children) 80326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 81804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def getName(self, default=""): 82804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.name or default 83326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 84804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def hasChildren(self): 85804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return bool(self.children) 86326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 87804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def getChildren(self): 88804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.children 89326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 90804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getDescendants(self): 91804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children: 92804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield child 93804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for descendant in child._getDescendants() : 94804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield descendant 95326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 96804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def getChildFromName(self, childName): 97326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 98804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children : 99326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 100804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if child.getName() == childName : 101804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return child 102326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 103804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Child %s not found" % childName, logging.ERROR) 104326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 105804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Child list :") 106326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 107804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children : 108804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug(" - %s" % child) 109326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 110804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise ChildNotFoundError(self, childName) 111326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 112326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 113804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def addChild(self, child): 114804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("new child: " + child.name) 115804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.children.append(child) 116804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard child._adoptedBy(self) 117326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 118804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _adoptedBy(self, parent): 119804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard assert(not self.parent) 120804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.parent = parent 121326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 122804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getElementNames(self, elementList): 123804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return (substate.name for substate in elementList) 124326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 125804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _description(self, withCoverage, withNbUse): 126804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard description = self.name 127326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 128804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if withNbUse or withCoverage : 129804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard description += " has been used " + str(self.nbUse) + " time" 130326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 131804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if withCoverage : 132804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard description += self._coverageFormating(self._getCoverage()) 133326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 134804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return description 135326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 136326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 137804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getCoverage(self): 138804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Return the coverage of the element between 0 and 1 139326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 140804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard If the element has no coverage dependency (usually child) return 0 or 1. 141804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard otherwise the element coverage is the dependency coverage average""" 142804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard coverageDependanceElements = list(self._getCoverageDependanceElements()) 143326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 144804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard nbcoverageDependence = len(coverageDependanceElements) 145326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 146804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if nbcoverageDependence == 0: 147804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if self.nbUse == 0: 148804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return 0 149804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else: 150804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return 1 151326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 152804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard coverageDependenceValues = (depElement._getCoverage() 153804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for depElement in coverageDependanceElements) 154326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 155804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return sum(coverageDependenceValues) / nbcoverageDependence 156326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 157804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getCoverageDependanceElements(self): 158804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.children 159326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 160804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _coverageFormating(self, coverage): 161804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # If no coverage provided 162804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not coverage : 163804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return "" 164326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 165804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Calculate coverage 166804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return " (%s coverage)" % self._number2percent(coverage) 167326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 168804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard @staticmethod 169804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _number2percent(number): 170804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Format a number to a integer % string 171326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 172804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard example: _number2percent(0.6666) -> "67%" 173804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """ 174804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return "{0:.0f}%".format(100 * number) 175326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 176326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 177804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _dumpDescription(self, withCoverage, withNbUse): 178326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 179804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("yelding description") 180804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield RankedLine(self._description(withCoverage, withNbUse), lineSuffix="") 181326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 182804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for dumped in self._dumpPropagate(withCoverage, withNbUse) : 183804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield dumped 184326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 185804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _dumpPropagate(self, withCoverage, withNbUse): 186326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 187804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children : 188804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for dumpedDescription in child._dumpDescription(withCoverage, withNbUse) : 189804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield dumpedDescription.increasedRank() 190326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 191326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 192804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def dump(self, withCoverage=False, withNbUse=True): 193326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 194804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return "\n".join( 195804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard str(dumpedDescription) for dumpedDescription in 196804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._dumpDescription(withCoverage, withNbUse)) 197326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 198804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def exportToXML(self, domElement=None): 199804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if domElement == None: 200804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard domElement = xml.dom.minidom.Element(self.tag) 20102726ec37a9686572f825520a04700061ffe5d06Kevin Rocard 202804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._XMLaddAttributes(domElement) 203326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 204804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children : 205804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard domElement.appendChild(child.exportToXML()) 206326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 207804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return domElement 208326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 209804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _XMLaddAttributes(self, domElement): 210804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard attributes = self._getXMLAttributes() 211326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 212804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard coverage = self._getCoverage() 213804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if coverage != None : 214804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard attributes["Coverage"] = self._number2percent(coverage) 215326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 216804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for key, value in attributes.items(): 217804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard domElement.setAttribute(key, value) 218326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 219804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getXMLAttributes(self): 220804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return { 221804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "Name": self.name, 222804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "NbUse": str(self.nbUse) 223804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard } 224326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 225804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _incNbUse(self): 226804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.nbUse += 1 227326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 228804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def childUsed(self, child): 229804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 230804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Propagate to parent 231804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._tellParentThatChildUsed() 232326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 233804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _tellParentThatChildUsed(self): 234804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if self.parent : 235804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.parent.childUsed(self) 236326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 237326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 238804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def parentUsed(self): 239804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 240804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Propagate to children 241804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children : 242804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard child.parentUsed() 243326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 244804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def hasBeenUsed(self): 245804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.nbUse > 0 246326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 247804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def operationOnChild(self, path, operation): 248326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 249804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if path: 250804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self._operationPropagate(path, operation) 251804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 252804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("operating on self") 253804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return operation(self) 254326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 255804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _operationPropagate(self, path, operation): 256326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 257804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childName = path.pop(0) 258804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard child = self.getChildFromName(childName) 259326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 260804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return child.operationOnChild(path, operation) 261326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 262326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 263326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 264804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def debug(self, stringOrFunction, level=logging.DEBUG): 265804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Print a debug line on stderr in tree form 266326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 267804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard If the debug line is expensive to generate, provide callable 268804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard object, it will be called if log is enable for this level. 269804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard This callable object should return the logline string. 270804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """ 271804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if logger.isEnabledFor(level): 272326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 273804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # TODO: use buildin callable if python >= 3.2 274804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if hasattr(stringOrFunction, "__call__"): 275804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard string = stringOrFunction() 276804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else: 277804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard string = stringOrFunction 278326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 279804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard rankedLine = DebugRankedLine("%s: %s" % (self, string)) 280804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._logDebug(rankedLine, level) 281326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 282804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _logDebug(self, rankedLine, level): 283326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 284804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if self.parent: 285804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.parent._logDebug(rankedLine.increasedRank(), level) 286804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 287804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.log(level, str(rankedLine)) 288326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 289326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 290326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 291326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 292326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass FromDomElement(Element): 293804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, DomElement): 294804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._initFromDom(DomElement) 295804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().__init__(self.name) 296326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 297326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 298804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _initFromDom(self, DomElement): 299804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.name = DomElement.getAttribute("Name") 300326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 301326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 302326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 303326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass DomElementLocation(): 304804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, classConstructor, path=None): 305804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.classConstructor = classConstructor 306804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if path : 307804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.path = path 308804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 309804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.path = [] 310326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 311804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.path.append(classConstructor.tag) 312326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 313326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 314326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass DomPopulatedElement(Element): 315804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Default child populate 316326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 317804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard Look for each dom element with tag specified in self.tag 318804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard and instantiate it with the dom element 319804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """ 320804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = [] 321326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 322804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def populate(self, dom): 323326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 324804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for childDomElementLocation in self.childClasses : 325326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 326804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Looking for child %s in path %s" % ( 327804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childDomElementLocation.path[-1], childDomElementLocation.path)) 328326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 329804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for childDomElement in self._findChildFromTagPath(dom, childDomElementLocation.path) : 330326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 331804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childElement = childDomElementLocation.classConstructor(childDomElement) 332804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(childElement) 333326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 334804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childElement.populate(childDomElement) 335326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 336804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _findChildFromTagPath(self, dom, path): 337804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not path : 338804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield dom 339804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 340804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Copy list 341804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard path = list(path) 342326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 343804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = path.pop(0) 344326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 345804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Find element with tag 346804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Going to find elements with tag %s in %s" % (tag, dom)) 347804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug(lambda: "Nb of solutions: %s" % len(dom.getElementsByTagName(tag))) 348326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 349804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for elementByTag in dom.getElementsByTagName(tag) : 350326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 351804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Found element: %s" % elementByTag) 352326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 353804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # If the same tag is found 354804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if elementByTag in dom.childNodes : 355326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 356804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Yield next level 357804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for element in self._findChildFromTagPath(elementByTag, path) : 358804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield element 359326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 360326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 361326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Rule(Element): 362326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 363804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def usedIfApplicable(self, criteria): 364804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childApplicability = (child.usedIfApplicable(criteria) 365804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children) 366326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 367804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard isApplicable = self._isApplicable(criteria, childApplicability) 368326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 369804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if isApplicable : 370804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 371326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 372804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Rule applicability: %s" % isApplicable) 373804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard assert(isApplicable == True or isApplicable == False) 374326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 375804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return isApplicable 376326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 377326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 378804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _isApplicable(self, criteria, childApplicability): 379804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Return the rule applicability depending on children applicability. 380cf031996ede8428065b6d7648e34720a1874f5faKevin Rocard 381804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard If at least one child is applicable, return true""" 382804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Lazy evaluation as in the PFW 383804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return all(childApplicability) 384326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 385326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 386326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CriterionRule(FromDomElement, DomPopulatedElement, Rule): 387804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "SelectionCriterionRule" 388804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = [] 389804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard isApplicableOperations = { 390804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "Includes" : lambda criterion, value: criterion.stateIncludes(value), 391804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "Excludes" : lambda criterion, value: not criterion.stateIncludes(value), 392804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "Is" : lambda criterion, value: criterion.stateIs(value), 393804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "IsNot" : lambda criterion, value: not criterion.stateIs(value) 394804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard } 395326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 396804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _initFromDom(self, DomElement): 397804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.selectionCriterion = DomElement.getAttribute("SelectionCriterion") 398804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.matchesWhen = DomElement.getAttribute("MatchesWhen") 399804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.value = DomElement.getAttribute("Value") 400804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.name = "%s %s %s" % (self.selectionCriterion, self.matchesWhen, self.value) 401326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 402804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard applicableOperationWithoutValue = self.isApplicableOperations[self.matchesWhen] 403804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.isApplicableOperation = lambda criterion: applicableOperationWithoutValue(criterion, self.value) 404326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 405804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _isApplicable(self, criteria, childApplicability): 406326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 407804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return criteria.operationOnChild([self.selectionCriterion], 408804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.isApplicableOperation) 409326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 410326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 411326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CompoundRule(FromDomElement, DomPopulatedElement, Rule): 412804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """CompoundRule can be of type ALL or ANY""" 413804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "CompoundRule" 414804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Declare childClasses but define it at first class instantiation 415804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = None 416326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 417804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, dom): 418804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Define childClasses at first class instantiation 419804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if self.childClasses == None : 420804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.childClasses = [DomElementLocation(CriterionRule), 421804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard DomElementLocation(CompoundRule)] 422804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().__init__(dom) 423326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 424804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _initFromDom(self, DomElement): 425326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 426804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard type = DomElement.getAttribute("Type") 427804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.ofTypeAll = {"All" : True, "Any" : False}[type] 428804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.name = type 429326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 430804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _isApplicable(self, criteria, childApplicability): 431804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if self.ofTypeAll : 432804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard applicability = super()._isApplicable(criteria, childApplicability) 433804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else: 434804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Lazy evaluation as in the PFW 435804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard applicability = any(childApplicability) 436326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 437804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return applicability 438326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 439326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass RootRule(DomPopulatedElement, Rule): 440804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "RootRule" 441804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = [DomElementLocation(CompoundRule)] 442326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 443804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def populate(self, dom): 444804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().populate(dom) 445804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Children: %s" % self.children) 446804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # A configuration can only have one or no rule 447804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard assert(len(self.children) <= 1) 448326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 449804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getCoverageDependanceElements(self): 450804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self._getDescendants() 451326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 452326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 453326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CriteronStates(Element): 454804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Root of configuration application criterion state""" 455804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "CriterionStates" 456326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 457804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def parentUsed(self, criteria): 458804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Add criteria to child if not exist, if exist increase it's nbUse""" 459804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 460326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 461804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard matches = [child for child in self.children if child == criteria] 462326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 463804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard assert(len(matches) <= 1) 464326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 465804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if matches : 466804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Criteria state has already been encounter") 467804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard currentcriteria = matches[0] 468804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 469804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Criteria state has never been encounter, saving it") 470804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard currentcriteria = criteria 471804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(criteria) 472326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 473804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard currentcriteria.parentUsed() 474326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 475326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 476326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 477326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Configuration(FromDomElement, DomPopulatedElement): 478804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "Configuration" 479804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = [] 480326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 481804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard class IneligibleConfigurationAppliedError(CustomError): 48297dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard 483804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, configuration, criteria): 484804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.configuration = configuration 485804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria = criteria 48697dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard 487804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 48897dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard 489804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return ("Applying ineligible %s, " 490804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "rule:\n%s\n" 491804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "Criteria current state:\n%s" % ( 492804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.configuration, 493804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.configuration.rootRule.dump(withCoverage=False, withNbUse=False), 494804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria.dump(withCoverage=False, withNbUse=False) 495804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard )) 49697dbd35c75ee252a674aff3d66293d55fc0b35a5Kevin Rocard 497804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, DomElement): 498804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().__init__(DomElement) 499326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 500804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.rootRule = RootRule("RootRule") 501804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(self.rootRule) 502326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 503804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteronStates = CriteronStates("CriterionStates") 504804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(self.criteronStates) 505326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 506804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def populate(self, dom): 507804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Delegate to rootRule 508804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.rootRule.populate(dom) 509326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 510804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getCoverage(self): 511804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Delegate to rootRule 512804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.rootRule._getCoverage() 513326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 514804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def used(self, criteria): 515326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 516804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 517326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 518804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Propagate use to parents 519804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._tellParentThatChildUsed() 520326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 521804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Propagate to criterion coverage 522804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteronStates.parentUsed(criteria.export()) 523326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 524804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Propagate to rules 525804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not self.rootRule.usedIfApplicable(criteria) : 526326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 527804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Applied but rule does not match current " 5283aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard "criteria (parent: %s) " % self.parent.name, 529804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logging.ERROR) 530326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 531804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise self.IneligibleConfigurationAppliedError(self, criteria.export()) 532326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 533804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _dumpPropagate(self, withCoverage, withNbUse): 534804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Going to ask %s for description" % self.rootRule) 535804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for dumpedDescription in self.rootRule._dumpDescription( 536804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard withCoverage=withCoverage, 537804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard withNbUse=withNbUse) : 538804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield dumpedDescription.increasedRank() 539326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 540804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Going to ask %s for description" % self.criteronStates) 541804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for dumpedDescription in self.criteronStates._dumpDescription( 542804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard withCoverage=False, 543804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard withNbUse=withNbUse) : 544804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard yield dumpedDescription.increasedRank() 545326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 546326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 547326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Domain(FromDomElement, DomPopulatedElement): 548804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "ConfigurableDomain" 549804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = [DomElementLocation(Configuration, ["Configurations"])] 550326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 551326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 552326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Domains(DomPopulatedElement): 553804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "Domains" 554804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard childClasses = [DomElementLocation(Domain, ["ConfigurableDomains"])] 555326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 556326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 557326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass RankedLine(): 558804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, string, 559804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard stringPrefix="|-- ", 560804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard rankString="| ", 561804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard linePrefix="", 562804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard lineSuffix="\n"): 563804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.string = string 564804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.rank = 0 565804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.stringPrefix = stringPrefix 566804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.rankString = rankString 567804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.linePrefix = linePrefix 568804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.lineSuffix = lineSuffix 569804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 570804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def increasedRank(self): 571804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.rank += 1 572804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self 573804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 574804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 575804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.linePrefix + \ 576804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.rank * self.rankString + \ 577804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.stringPrefix + \ 578804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.string + \ 579804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.lineSuffix 580326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 581326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass DebugRankedLine(RankedLine): 582326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 583804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, string, lineSuffix=""): 584804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().__init__(string, 585804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard stringPrefix="", 586804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard rankString=" ", 587804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard linePrefix="", 588804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard lineSuffix=lineSuffix) 589326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 590326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 591326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass CriterionState(Element): 592804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "CriterionState" 593804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def used(self): 594804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 595326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 596326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 597326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Criterion(Element): 598804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "Criterion" 599804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard inclusivenessTranslate = {True: "Inclusive", False: "Exclusive"} 6003aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 601804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard class ChangeRequestToNonAccessibleState(CustomError): 602804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, requestedState, detail): 603804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.requestedState = requestedState 604804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.detail = detail 605556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard 606804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 607804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return ("Change request to non accessible state %s. Detail: %s" % 608804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard (self.requestedState, self.detail)) 609556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard 610804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, name, isInclusif, 611804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard stateNamesList, currentStateNamesList, 612804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ignoreIntegrity=False): 613804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().__init__(name) 614804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.isInclusif = isInclusif 615326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 616804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for state in stateNamesList : 617804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(CriterionState(state)) 618326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 619804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.currentState = [] 620804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.initStateNamesList = list(currentStateNamesList) 621804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.changeState(self.initStateNamesList, ignoreIntegrity) 622326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 623804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def reset(self): 624804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Set current state as provided at initialisation 625804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.changeState(self.initStateNamesList, ignoreIntegrity=True) 626326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 627804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def changeState(self, subStateNames, ignoreIntegrity=False): 628804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Changing state from: %s to: %s" % ( 629804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard list(self._getElementNames(self.currentState)), 630804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard subStateNames)) 631326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 632804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not ignoreIntegrity and not self.isIntegre(subStateNames): 633804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise self.ChangeRequestToNonAccessibleState(subStateNames, 634804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "An exclusive criterion must have a non empty state") 635326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 636804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard newCurrentState = [] 637804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for subStateName in subStateNames : 638804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard subState = self.getChildFromName(subStateName) 639804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard subState.used() 640804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard newCurrentState.append(subState) 641326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 642804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.currentState = newCurrentState 643326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 644804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._incNbUse() 645804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self._tellParentThatChildUsed() 646326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 647804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def isIntegre(self, subStateNames): 648804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.isInclusif or len(subStateNames) == 1 649556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard 650804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def childUsed(self, child): 651804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.currentState = child 652804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().childUsed(child) 653556538e2bda03b54bdd82c5813a5286e90a39f67Kevin Rocard 654804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def export(self): 655804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard subStateNames = self._getElementNames(self.currentState) 656804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return Criterion(self.name, self.isInclusif, subStateNames, subStateNames, 657804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ignoreIntegrity=True) 658326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 659804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def stateIncludes(self, subStateName): 660804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard subStateCurrentNames = list(self._getElementNames(self.currentState)) 661326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 662804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Testing if %s is included in %s" % (subStateName, subStateCurrentNames)) 663326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 664804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard isIncluded = subStateName in subStateCurrentNames 665804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("IsIncluded: %s" % isIncluded) 666326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 667804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return isIncluded 668326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 669326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 670804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def stateIs(self, subStateNames): 671804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if len(self.currentState) != 1 : 672804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return False 673804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 674804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return self.stateIncludes(subStateNames) 675326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 676804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _getXMLAttributes(self): 677804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard attributes = super()._getXMLAttributes() 678804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard attributes["Type"] = self.inclusivenessTranslate[self.isInclusif] 679804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return attributes 6803aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 681326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 682326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Criteria(Element): 683804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "Criteria" 684326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 685804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard class DuplicatedCriterionError(DuplicatedChildError): 686804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard pass 687d077c557e360615a67d97ee249260a1ef7919f09Kevin Rocard 688804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def export(self): 689804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debug("Exporting criteria") 690804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard assert(self.children) 691326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 692804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard exported = Criteria(self.name) 693804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for child in self.children : 694804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard exported.addChild(child.export()) 695804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return exported 696326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 697804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def addChild(self, child): 698804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if child in self.children: 699804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise self.DuplicatedCriterionError(self, child) 700804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().addChild(child) 7013aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 7023aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocardclass ConfigAppliedWithoutCriteriaError(CustomError): 703804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, configurationName, domainName): 704804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.configurationName = configurationName 705804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domainName = domainName 706804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __str__(self): 707804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return ('Applying configuration "%s" from domain "%s" before declaring criteria' % 708804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard (self.configurationName, self.domainName)) 709326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 710326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass ParsePFWlog(): 711804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard MATCH = "match" 712804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ACTION = "action" 713804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 714804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, domains, criteria, ErrorsToIgnore=()): 715804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 716804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domains = domains; 717804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria = criteria; 718804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.ErrorsToIgnore = ErrorsToIgnore 719326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 720804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard configApplicationRegext = r""".*Applying configuration "(.*)" from domain "([^"]*)""" 721804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard matchConfigApplicationLine = re.compile(configApplicationRegext).match 722804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 723804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionCreationRegext = ", ".join([ 724804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard r""".*Criterion name: (.*)""", 725804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard r"""type kind: (.*)""", 726804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard r"""current state: (.*)""", 727804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard r"""states: {(.*)}""" 728804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ]) 729804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard matchCriterionCreationLine = re.compile(criterionCreationRegext).match 730326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 731804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard changingCriterionRegext = r""".*Selection criterion changed event: Criterion name: (.*), current state: ([^\n\r]*)""" 732804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard matchChangingCriterionLine = re.compile(changingCriterionRegext).match 733326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 734804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.lineLogTypes = [ 735804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard { 736804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.MATCH: matchConfigApplicationLine, 737804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.ACTION: self._configApplication 738804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard }, { 739804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.MATCH: matchCriterionCreationLine, 740804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.ACTION: self._criterionCreation 741804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard }, { 742804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.MATCH: matchChangingCriterionLine, 743804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.ACTION: self._changingCriterion 744804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard } 745804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ] 746326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 747804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard @staticmethod 748804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _formatCriterionList(liststring, separator): 749804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard list = liststring.split(separator) 750804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if len(list) == 1 and list[0] == "<none>": 751804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard list = [] 752804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return list 753804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 754804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _criterionCreation(self, matchCriterionCreation): 755804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Unpack 756804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionName, criterionType, currentCriterionStates, criterionStates = matchCriterionCreation.group(1, 2, 3, 4) 757326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 758804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionStateList = self._formatCriterionList(criterionStates, ", ") 759326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 760804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionIsInclusif = {"exclusive" : False, "inclusive" : True}[criterionType] 761326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 762804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard currentcriterionStateList = self._formatCriterionList(currentCriterionStates, "|") 763326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 764804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.info("Creating criterion: " + criterionName + 765804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard " (" + criterionType + ") " + 766804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard " with current state: " + str(currentcriterionStateList) + 767804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ", possible states:" + str(criterionStateList)) 768326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 769804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard try: 770804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria.addChild(Criterion( 771804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionName, 772804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionIsInclusif, 773804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionStateList, 774804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard currentcriterionStateList 775804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard )) 776804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard except self.criteria.DuplicatedCriterionError as ex: 777804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.debug(ex) 778804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning("Reseting criterion %s. Did you reset the PFW ?" % criterionName) 779804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria.operationOnChild( 780804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard [criterionName], 781804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard lambda criterion: criterion.reset() 782804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 783ea87422e14735633cb8e28de114a18e22eaa82fbKevin Rocard 784ea87422e14735633cb8e28de114a18e22eaa82fbKevin Rocard 785326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 786804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _changingCriterion(self, matchChangingCriterion): 787804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Unpack 788804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard criterionName, newCriterionSubStateNames = matchChangingCriterion.group(1, 2) 789326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 790804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard newCriterionState = self._formatCriterionList(newCriterionSubStateNames, "|") 791326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 792804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.info("Changing criterion %s to %s" % (criterionName , newCriterionState)) 7933aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 794804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard path = [criterionName] 795804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard changeCriterionOperation = lambda criterion : criterion.changeState(newCriterionState) 796804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria.operationOnChild(path, changeCriterionOperation) 797326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 798804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _configApplication(self, matchConfig): 799804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Unpack 800804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard configurationName, domainName = matchConfig.group(1, 2) 8013aa0db4be952157c2842b91a1606cc0edac9e63dKevin Rocard 802804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Check that at least one criterion exist 803804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not self.criteria.hasChildren() : 804804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.error("Applying configuration before declaring criteria") 805804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.info("Is the log starting at PFW boot ?") 806804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise ConfigAppliedWithoutCriteriaError(configurationName, domainName) 807326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 808804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Change criterion state 809804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard path = [domainName, configurationName] 810804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard usedOperation = lambda element : element.used(self.criteria) 811326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 812804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.info("Applying configuration %s from domain %s" % ( 813804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard configurationName, domainName)) 814804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 815804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domains.operationOnChild(path, usedOperation) 816326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 817326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 818804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def _digest(self, lineLogType, lineLog): 8199050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard 820804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard match = lineLogType[self.MATCH](lineLog) 821804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if match : 822804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard lineLogType[self.ACTION](match) 823804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return True 824804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return False 825326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 8269050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard 827804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def parsePFWlog(self, lines): 828804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for lineNb, lineLog in enumerate(lines): 829326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 830804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.debug("Parsing line :%s" % lineLog.rstrip()) 831326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 832804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard digested = (self._digest(lineLogType, lineLog) 833804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard for lineLogType in self.lineLogTypes) 834326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 835804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard try: 836804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard success = any(digested) 8379050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard 838804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Catch some exception in order to print the current parsing line, 839804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # then raise the exception again if not continue of error 840804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard except CustomError as ex: 841804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.error('Error raised while parsing line %s: "%s"' % 842804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard (lineNb, repr(lineLog))) 8439050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard 844804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # If exception is a subclass of ErrorsToIgnore, log it and continue 845804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # otherwise raise it again. 846804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not issubclass(type(ex), self.ErrorsToIgnore): 847804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise ex 848804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else: 849804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.error('Ignoring exception:"%s", ' 850804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 'can not guarantee database integrity' % ex) 851804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else: 852804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not success: 853804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.debug("Line does not match, dropped") 854326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 855326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 856326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass Root(Element): 857804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard tag = "CoverageReport" 858804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self, name, dom): 859804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().__init__(name) 860804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Create domain tree 861804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domains = Domains("Domains") 862804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domains.populate(dom) 863804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(self.domains) 864804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Create criterion list 865804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.criteria = Criteria("CriterionRoot") 866804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.addChild(self.criteria) 867804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 868804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def exportToXML(self): 869804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """Export tree to an xml document""" 870804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard impl = xml.dom.minidom.getDOMImplementation() 871804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard newdoc = impl.createDocument(namespaceURI=None, qualifiedName=self.tag, doctype=None) 872804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard super().exportToXML(newdoc.documentElement) 873804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 874804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard return newdoc 875326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 876326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard# ============================ 877326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard# Command line argument parser 878326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard# ============================ 879326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 880326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 881326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardclass ArgumentParser: 882804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """class that parse command line arguments with argparse library 883804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 884804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard Result of parsing are the class attributes. 885804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """ 886804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard levelTranslate = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG] 887804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 888804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard def __init__(self): 889804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 890804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard try: 891804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # As argparse is only in the stdlib since python 3.2, 892804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # testing its availability 893804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard import argparse 894804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 895804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard except ImportError: 896804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning("Unable to import argparse " 897804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "(parser for command-line options and arguments), " 898804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "using default argument values:") 899804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 900804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning(" - InputFile: stdin") 901804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.inputFile = sys.stdin 902804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 903804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning(" - OutputFile: stdout") 904804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.outputFile = sys.stdout 905804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 906804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard try: 907804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domainsFile = sys.argv[1] 908804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard except IndexError as ex: 909804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.fatal("No domain file provided (first argument)") 910804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard raise ex 911804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else: 912804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning(" - Domain file: " + self.domainsFile) 913804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 914804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning(" - Output format: xml") 915804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.XMLreport = True 916804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 917804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.warning(" - Debug level: error") 918804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debugLevel = logging.ERROR 919804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 920804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 921804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser = argparse.ArgumentParser(description='Generate PFW report') 922804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 923804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser.add_argument( 924804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 'domainsFile', 925804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard type=argparse.FileType('r'), 926804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="the PFW domain XML file" 927804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 928804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser.add_argument( 929804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 'pfwlog', nargs='?', 930804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard type=argparse.FileType('r'), default=sys.stdin, 931804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="the PFW log file, default stdin" 932804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 933804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser.add_argument( 934804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard '-o', '--output', 935804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dest="outputFile", 936804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard type=argparse.FileType('w'), default=sys.stdout, 937804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="the coverage report output file, default stdout" 938804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 939804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser.add_argument( 940804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard '-v', '--verbose', 941804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dest="debugLevel", default=0, 942804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard action='count', 943804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="print debug warnings from warning (default) to debug (-vv)" 944804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 945804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 946804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard outputFormatGroupe = myArgParser.add_mutually_exclusive_group(required=False) 947804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 948804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard outputFormatGroupe.add_argument( 949804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard '--xml', 950804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dest="xmlFlag", 951804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard action='store_true', 952804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help=" XML coverage output report" 953804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 954804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard outputFormatGroupe.add_argument( 955804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard '--raw', 956804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dest="rawFlag", 957804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard action='store_true', 958804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="raw coverage output report" 959804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 960804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 961804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser.add_argument( 962804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard '--ignore-incoherent-criterion-state', 963804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dest="incoherentCriterionFlag", 964804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard action='store_true', 965804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="ignore criterion transition to incoherent state" 966804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 967804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 968804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard myArgParser.add_argument( 969804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard '--ignore-ineligible-configuration-application', 970804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dest="ineligibleConfigurationApplicationFlag", 971804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard action='store_true', 972804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard help="ignore application of configuration with a false rule " 973804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard "(not applicable configuration)" 974804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard ) 975804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 976804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Process command line arguments 977804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard options = myArgParser.parse_args() 978804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 979804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Mapping to attributes 980804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.inputFile = options.pfwlog 981804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.outputFile = options.outputFile 982804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.domainsFile = options.domainsFile 983804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 984804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Output report in xml if flag not set 985804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.XMLreport = not options.rawFlag 986804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 987804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Setting logger level 988804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard levelCapped = min(options.debugLevel, len(self.levelTranslate) - 1) 989804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.debugLevel = self.levelTranslate[levelCapped] 990804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 991804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Setting ignore options 992804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard errorToIgnore = [] 993804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if options.ineligibleConfigurationApplicationFlag : 994804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard errorToIgnore.append(Configuration.IneligibleConfigurationAppliedError) 995804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 996804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if options.incoherentCriterionFlag: 997804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard errorToIgnore.append(Criterion.ChangeRequestToNonAccessibleState) 998804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard 999804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard self.errorToIgnore = tuple(errorToIgnore) 10009050c81c8f9a63aa95e7230705e00585bd0ecec5Kevin Rocard 1001326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1002326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1003326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocarddef main(): 1004326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1005804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard errorDuringLogParsing = -1 1006804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard errorDuringArgumentParsing = 1 100753493b2f22bc2d491f7607672e1d07e588677efaKevin Rocard 1008804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard try: 1009804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard commandLineArguments = ArgumentParser() 1010804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard except LookupError as ex: 1011804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.error("Error during argument parsing") 1012804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.debug(str(ex)) 1013804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard sys.exit(errorDuringArgumentParsing) 1014326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1015804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Setting logger level 1016804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.setLevel(commandLineArguments.debugLevel) 1017804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.info("Log level set to: %s" % 1018804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logging.getLevelName(commandLineArguments.debugLevel)) 1019326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1020804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Create tree from XML 1021804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard dom = xml.dom.minidom.parse(commandLineArguments.domainsFile) 1022326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1023804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Create element tree 1024804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard root = Root("DomainCoverage", dom) 1025326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1026804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Parse PFW events 1027804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard parser = ParsePFWlog(root.domains, root.criteria, commandLineArguments.errorToIgnore) 102853493b2f22bc2d491f7607672e1d07e588677efaKevin Rocard 1029804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard try: 1030804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard parser.parsePFWlog(commandLineArguments.inputFile.readlines()) 1031804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard except CustomError as ex: 1032804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard logger.fatal("Error during parsing log file %s: %s" % 1033804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard (commandLineArguments.inputFile, ex)) 1034804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard sys.exit(errorDuringLogParsing) 1035326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1036804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard # Output report 1037804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard outputFile = commandLineArguments.outputFile 1038326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1039804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard if not commandLineArguments.XMLreport : 1040804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard outputFile.write("%s\n" % root.dump(withCoverage=True, withNbUse=True)) 1041804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard else : 1042804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard outputFile.write(root.exportToXML().toprettyxml()) 1043326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1044326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1045326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocardif __name__ == "__main__" : 1046804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard """ Execute main if the python interpreter is running this module as the main program """ 1047804e064dcd02b87e04b9a189422cc14205e8125cKevin Rocard main() 1048326e39e42a801bff4b61655ebc0e3ff759c208ffKevin Rocard 1049