Changeset 65040 in vbox
- Timestamp:
- Dec 31, 2016 2:29:50 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 112535
- Location:
- trunk/src/VBox/ValidationKit/testmanager
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/testmanager/core/build.py
r62548 r65040 479 479 Build database logic (covers build categories as well as builds). 480 480 """ 481 482 def __init__(self, oDb): 483 ModelLogicBase.__init__(self, oDb) 484 self.dCache = None; 481 485 482 486 # … … 609 613 self._oDb.maybeCommit(fCommit); 610 614 return True; 615 616 def cachedLookup(self, idBuild): 617 """ 618 Looks up the most recent BuildDataEx object for idBuild 619 via an object cache. 620 621 Returns a shared BuildDataEx object. None if not found. 622 Raises exception on DB error. 623 """ 624 if self.dCache is None: 625 self.dCache = self._oDb.getCache('BuildDataEx'); 626 oEntry = self.dCache.get(idBuild, None); 627 if oEntry is None: 628 self._oDb.execute('SELECT Builds.*, BuildCategories.*\n' 629 'FROM Builds, BuildCategories\n' 630 'WHERE Builds.idBuild = %s\n' 631 ' AND Builds.idBuildCategory = BuildCategories.idBuildCategory\n' 632 ' AND tsExpire = \'infinity\'::TIMESTAMP\n' 633 , (idBuild, )); 634 if self._oDb.getRowCount() == 0: 635 # Maybe it was deleted, try get the last entry. 636 self._oDb.execute('SELECT Builds.*, BuildCategories.*\n' 637 'FROM Builds, BuildCategories\n' 638 'WHERE Builds.idBuild = %s\n' 639 ' AND Builds.idBuildCategory = BuildCategories.idBuildCategory\n' 640 'ORDER BY tsExpire DESC\n' 641 'LIMIT 1\n' 642 , (idBuild, )); 643 elif self._oDb.getRowCount() > 1: 644 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idBuild)); 645 646 if self._oDb.getRowCount() == 1: 647 aaoRow = self._oDb.fetchOne(); 648 oEntry = BuildDataEx(); 649 oEntry.initFromDbRow(aaoRow); 650 self.dCache[idBuild] = oEntry; 651 return oEntry; 611 652 612 653 -
trunk/src/VBox/ValidationKit/testmanager/core/buildblacklist.py
r62484 r65040 123 123 Build Back List logic. 124 124 """ 125 126 def __init__(self, oDb): 127 ModelLogicBase.__init__(self, oDb) 128 self.dCache = None; 125 129 126 130 def fetchForListing(self, iStart, cMaxRows, tsNow): … … 223 227 self._oDb.maybeCommit(fCommit); 224 228 return True; 229 230 231 def cachedLookup(self, idBlacklisting): 232 """ 233 Looks up the most recent BuildBlacklistData object for idBlacklisting 234 via an object cache. 235 236 Returns a shared BuildBlacklistData object. None if not found. 237 Raises exception on DB error. 238 """ 239 if self.dCache is None: 240 self.dCache = self._oDb.getCache('BuildBlacklistData'); 241 oEntry = self.dCache.get(idBlacklisting, None); 242 if oEntry is None: 243 self._oDb.execute('SELECT *\n' 244 'FROM BuildBlacklist\n' 245 'WHERE idBlacklisting = %s\n' 246 ' AND tsExpire = \'infinity\'::TIMESTAMP\n' 247 , (idBlacklisting, )); 248 if self._oDb.getRowCount() == 0: 249 # Maybe it was deleted, try get the last entry. 250 self._oDb.execute('SELECT *\n' 251 'FROM BuildBlacklist\n' 252 'WHERE idBlacklisting = %s\n' 253 'ORDER BY tsExpire DESC\n' 254 'LIMIT 1\n' 255 , (idBlacklisting, )); 256 elif self._oDb.getRowCount() > 1: 257 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idBlacklisting)); 258 259 if self._oDb.getRowCount() == 1: 260 aaoRow = self._oDb.fetchOne(); 261 oEntry = BuildBlacklistData(); 262 oEntry.initFromDbRow(aaoRow); 263 self.dCache[idBlacklisting] = oEntry; 264 return oEntry; 225 265 226 266 -
trunk/src/VBox/ValidationKit/testmanager/core/buildsource.py
r62484 r65040 154 154 Build source database logic. 155 155 """ 156 157 def __init__(self, oDb): 158 ModelLogicBase.__init__(self, oDb) 159 self.dCache = None; 156 160 157 161 # … … 325 329 return True; 326 330 331 def cachedLookup(self, idBuildSrc): 332 """ 333 Looks up the most recent BuildSourceData object for idBuildSrc 334 via an object cache. 335 336 Returns a shared BuildSourceData object. None if not found. 337 Raises exception on DB error. 338 """ 339 if self.dCache is None: 340 self.dCache = self._oDb.getCache('BuildSourceData'); 341 oEntry = self.dCache.get(idBuildSrc, None); 342 if oEntry is None: 343 self._oDb.execute('SELECT *\n' 344 'FROM BuildSources\n' 345 'WHERE idBuildSrc = %s\n' 346 ' AND tsExpire = \'infinity\'::TIMESTAMP\n' 347 , (idBuildSrc, )); 348 if self._oDb.getRowCount() == 0: 349 # Maybe it was deleted, try get the last entry. 350 self._oDb.execute('SELECT *\n' 351 'FROM BuildSources\n' 352 'WHERE idBuildSrc = %s\n' 353 'ORDER BY tsExpire DESC\n' 354 'LIMIT 1\n' 355 , (idBuildSrc, )); 356 elif self._oDb.getRowCount() > 1: 357 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idBuildSrc)); 358 359 if self._oDb.getRowCount() == 1: 360 aaoRow = self._oDb.fetchOne(); 361 oEntry = BuildSourceData(); 362 oEntry.initFromDbRow(aaoRow); 363 self.dCache[idBuildSrc] = oEntry; 364 return oEntry; 327 365 328 366 # -
trunk/src/VBox/ValidationKit/testmanager/core/failurereason.py
r62484 r65040 213 213 'ORDER BY sShort ASC\n' 214 214 'LIMIT %s OFFSET %s\n' 215 , ( tsNow, tsNow, idFailureCategory, cMaxRows, iStart,));215 , ( idFailureCategory, tsNow, tsNow, cMaxRows, iStart,)); 216 216 217 217 aoRows = [] -
trunk/src/VBox/ValidationKit/testmanager/core/globalresource.py
r62484 r65040 120 120 """ 121 121 122 def __init__(self, oDb): 123 ModelLogicBase.__init__(self, oDb) 124 self.dCache = None; 125 122 126 def fetchForListing(self, iStart, cMaxRows, tsNow): 123 127 """ … … 146 150 aoRows.append(GlobalResourceData().initFromDbRow(aoRow)) 147 151 return aoRows 152 153 154 def cachedLookup(self, idGlobalRsrc): 155 """ 156 Looks up the most recent GlobalResourceData object for idGlobalRsrc 157 via an object cache. 158 159 Returns a shared GlobalResourceData object. None if not found. 160 Raises exception on DB error. 161 """ 162 if self.dCache is None: 163 self.dCache = self._oDb.getCache('GlobalResourceData'); 164 oEntry = self.dCache.get(idGlobalRsrc, None); 165 if oEntry is None: 166 self._oDb.execute('SELECT *\n' 167 'FROM GlobalResources\n' 168 'WHERE idGlobalRsrc = %s\n' 169 ' AND tsExpire = \'infinity\'::TIMESTAMP\n' 170 , (idGlobalRsrc, )); 171 if self._oDb.getRowCount() == 0: 172 # Maybe it was deleted, try get the last entry. 173 self._oDb.execute('SELECT *\n' 174 'FROM GlobalResources\n' 175 'WHERE idGlobalRsrc = %s\n' 176 'ORDER BY tsExpire DESC\n' 177 'LIMIT 1\n' 178 , (idGlobalRsrc, )); 179 elif self._oDb.getRowCount() > 1: 180 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idGlobalRsrc)); 181 182 if self._oDb.getRowCount() == 1: 183 aaoRow = self._oDb.fetchOne(); 184 oEntry = GlobalResourceData(); 185 oEntry.initFromDbRow(aaoRow); 186 self.dCache[idGlobalRsrc] = oEntry; 187 return oEntry; 188 148 189 149 190 def getAll(self, tsEffective = None): -
trunk/src/VBox/ValidationKit/testmanager/core/schedgroup.py
r62484 r65040 425 425 SchedGroup logic. 426 426 """ 427 428 def __init__(self, oDb): 429 ModelLogicBase.__init__(self, oDb); 430 self.dCache = None; 427 431 428 432 # … … 610 614 return True; 611 615 616 617 def cachedLookup(self, idSchedGroup): 618 """ 619 Looks up the most recent SchedGroupData object for idSchedGroup 620 via an object cache. 621 622 Returns a shared SchedGroupData object. None if not found. 623 Raises exception on DB error. 624 """ 625 if self.dCache is None: 626 self.dCache = self._oDb.getCache('SchedGroup'); 627 628 oEntry = self.dCache.get(idSchedGroup, None); 629 if oEntry is None: 630 self._oDb.execute('SELECT *\n' 631 'FROM SchedGroups\n' 632 'WHERE idSchedGroup = %s\n' 633 ' AND tsExpire = \'infinity\'::TIMESTAMP\n' 634 , (idSchedGroup, )); 635 if self._oDb.getRowCount() == 0: 636 # Maybe it was deleted, try get the last entry. 637 self._oDb.execute('SELECT *\n' 638 'FROM SchedGroups\n' 639 'WHERE idSchedGroup = %s\n' 640 'ORDER BY tsExpire DESC\n' 641 'LIMIT 1\n' 642 , (idSchedGroup, )); 643 elif self._oDb.getRowCount() > 1: 644 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idSchedGroup)); 645 646 if self._oDb.getRowCount() == 1: 647 oEntry = SchedGroupData().initFromDbRow(self._oDb.fetchOne()); 648 self.dCache[idSchedGroup] = oEntry; 649 return oEntry; 612 650 613 651 -
trunk/src/VBox/ValidationKit/testmanager/core/systemchangelog.py
r65039 r65040 31 31 32 32 # Validation Kit imports. 33 from testmanager.core.base import ModelLogicBase;33 from testmanager.core.base import ModelLogicBase; 34 34 from testmanager.core.useraccount import UserAccountLogic; 35 from testmanager.core.systemlog import SystemLogData; 35 36 36 37 … … 40 41 """ 41 42 42 def __init__(self, tsEffective, oAuthor, s What, idWhat, sDesc):43 def __init__(self, tsEffective, oAuthor, sEvent, idWhat, sDesc): 43 44 self.tsEffective = tsEffective; 44 45 self.oAuthor = oAuthor; 45 self.s What = sWhat;46 self.sEvent = sEvent; 46 47 self.idWhat = idWhat; 47 48 self.sDesc = sDesc; … … 55 56 ## @name What kind of change. 56 57 ## @{ 57 ksWhat_TestBox = 'TestBox'; 58 ksWhat_TestCase = 'TestCase'; 59 ksWhat_Blacklisting = 'Blacklisting'; 60 ksWhat_Build = 'Build'; 61 ksWhat_BuildSource = 'BuildSource'; 62 ksWhat_FailureCategory = 'FailureCategory'; 63 ksWhat_FailureReason = 'FailureReason'; 64 ksWhat_GlobalRsrc = 'GlobalRsrc'; 65 ksWhat_SchedGroup = 'SchedGroup'; 66 ksWhat_SystemLog = 'SystemLog'; 67 ksWhat_TestGroup = 'TestGroup'; 68 ksWhat_User = 'User'; 69 ksWhat_TestResult = 'TestResult'; 58 ksWhat_TestBox = 'chlog::TestBox'; 59 ksWhat_TestCase = 'chlog::TestCase'; 60 ksWhat_Blacklisting = 'chlog::Blacklisting'; 61 ksWhat_Build = 'chlog::Build'; 62 ksWhat_BuildSource = 'chlog::BuildSource'; 63 ksWhat_FailureCategory = 'chlog::FailureCategory'; 64 ksWhat_FailureReason = 'chlog::FailureReason'; 65 ksWhat_GlobalRsrc = 'chlog::GlobalRsrc'; 66 ksWhat_SchedGroup = 'chlog::SchedGroup'; 67 ksWhat_TestGroup = 'chlog::TestGroup'; 68 ksWhat_User = 'chlog::User'; 69 ksWhat_TestResult = 'chlog::TestResult'; 70 70 ## @} 71 71 … … 84 84 ksWhat_GlobalRsrc: ( 'GlobalResources', 'idGlobalRsrc', None, ), 85 85 ksWhat_SchedGroup: ( 'SchedGroupes', 'idSchedGroup', None, ), 86 ksWhat_SystemLog: ( 'SystemLog', 'tsCreated', ksClue_TimestampId, ),87 86 ksWhat_TestGroup: ( 'TestGroupes', 'idTestGroup', None, ), 88 87 ksWhat_User: ( 'Users', 'idUser', None, ), 89 88 ksWhat_TestResult: ( 'TestResults', 'idTestResult', None, ), 90 89 }; 90 for sEvent in SystemLogData.kasEvents: 91 kdWhatToTable[sEvent] = ( 'SystemLog', 'tsCreated', ksClue_TimestampId, ); 91 92 92 93 ## @todo move to config.py? … … 155 156 sQuery = '(\n' 156 157 sQuery += ' SELECT NULL AS uidAuthor,\n'; 157 sQuery += ' tsCreated astsEffective,\n';158 sQuery += ' \'' + self.ksWhat_SystemLog + '\' AS sWhat,\n';159 sQuery += ' NULL AS idWhat,\n';160 sQuery += ' CONCAT(sEvent, \': \', sLogText)AS sDesc\n';158 sQuery += ' tsCreated AS tsEffective,\n'; 159 sQuery += ' sEvent AS sEvent,\n'; 160 sQuery += ' NULL AS idWhat,\n'; 161 sQuery += ' sLogText AS sDesc\n'; 161 162 sQuery += ' FROM SystemLog\n'; 162 163 sQuery += sWhereTime.replace('tsEffective', 'tsCreated'); -
trunk/src/VBox/ValidationKit/testmanager/core/testbox.py
r65039 r65040 995 995 # Maybe it was deleted, try get the last entry. 996 996 self._oDb.execute('SELECT TestBoxesWithStrings.*\n' 997 'FROM TestBoxes \n'997 'FROM TestBoxesWithStrings\n' 998 998 'WHERE idTestBox = %s\n' 999 999 'ORDER BY tsExpire DESC\n' -
trunk/src/VBox/ValidationKit/testmanager/core/testgroup.py
r62484 r65040 372 372 """ 373 373 374 def __init__(self, oDb): 375 ModelLogicBase.__init__(self, oDb) 376 self.dCache = None; 377 374 378 # 375 379 # Standard methods. … … 550 554 return True; 551 555 556 def cachedLookup(self, idTestGroup): 557 """ 558 Looks up the most recent TestGroupDataEx object for idTestGroup 559 via an object cache. 560 561 Returns a shared TestGroupDataEx object. None if not found. 562 Raises exception on DB error. 563 """ 564 if self.dCache is None: 565 self.dCache = self._oDb.getCache('TestGroupDataEx'); 566 oEntry = self.dCache.get(idTestGroup, None); 567 if oEntry is None: 568 fNeedTsNow = False; 569 self._oDb.execute('SELECT *\n' 570 'FROM TestGroups\n' 571 'WHERE idTestGroup = %s\n' 572 ' AND tsExpire = \'infinity\'::TIMESTAMP\n' 573 , (idTestGroup, )); 574 if self._oDb.getRowCount() == 0: 575 # Maybe it was deleted, try get the last entry. 576 self._oDb.execute('SELECT *\n' 577 'FROM TestGroups\n' 578 'WHERE idTestGroup = %s\n' 579 'ORDER BY tsExpire DESC\n' 580 'LIMIT 1\n' 581 , (idTestGroup, )); 582 fNeedTsNow = True; 583 elif self._oDb.getRowCount() > 1: 584 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idTestGroup)); 585 586 if self._oDb.getRowCount() == 1: 587 aaoRow = self._oDb.fetchOne(); 588 oEntry = TestGroupDataEx(); 589 tsNow = oEntry.initFromDbRow(aaoRow).tsEffective if fNeedTsNow else None; 590 oEntry.initFromDbRowEx(aaoRow, self._oDb, tsNow); 591 self.dCache[idTestGroup] = oEntry; 592 return oEntry; 593 552 594 553 595 # -
trunk/src/VBox/ValidationKit/testmanager/htdocs/css/common.css
r65010 r65040 411 411 } 412 412 413 /* 414 * Generic class for div elements wrapping pre inside a table. This prevents 415 * the <pre> from taking up way more screen space that available. 416 */ 417 .tdpre { 418 display: table; 419 table-layout: fixed; 420 width: 100%; 421 } 422 .tdpre pre { 423 overflow: auto; 424 } 425 413 426 414 427 /* … … 567 580 } 568 581 582 .tmsyschlogattr { 583 font-size: 0.64em; 584 } 569 585 570 586 /* -
trunk/src/VBox/ValidationKit/testmanager/webui/wuiadmin.py
r65039 r65040 167 167 # System Log actions. 168 168 # 169 self._dDispatch[self.ksActionSystemChangelogList] = self._actionSystemChangelogList; 169 170 self._dDispatch[self.ksActionSystemLogList] = self._actionSystemLogList; 170 self._dDispatch[self.ksActionSystemChangelogList] = self._actionSystemChangelogList;171 171 172 172 # -
trunk/src/VBox/ValidationKit/testmanager/webui/wuiadminsystemchangelog.py
r65039 r65040 30 30 31 31 32 from common import webutils; 33 32 34 # Validation Kit imports. 33 from testmanager.webui.wuicontentbase import WuiListContentBase #, WuiTmLink; 34 #from testmanager.core.testbox import TestBoxData; 35 #from testmanager.core.systemchangelog import SystemChangelogLogic; 36 #from testmanager.core.useraccount import UserAccountData; 35 from testmanager.webui.wuicontentbase import WuiListContentBase, WuiHtmlKeeper, WuiAdminLink, \ 36 WuiMainLink, WuiElementText, WuiHtmlBase; 37 38 from testmanager.core.base import AttributeChangeEntryPre; 39 from testmanager.core.buildblacklist import BuildBlacklistLogic, BuildBlacklistData; 40 from testmanager.core.build import BuildLogic, BuildData; 41 from testmanager.core.buildsource import BuildSourceLogic, BuildSourceData; 42 from testmanager.core.globalresource import GlobalResourceLogic, GlobalResourceData; 43 from testmanager.core.failurecategory import FailureCategoryLogic, FailureCategoryData; 44 from testmanager.core.failurereason import FailureReasonLogic, FailureReasonData; 45 from testmanager.core.systemlog import SystemLogData; 46 from testmanager.core.systemchangelog import SystemChangelogLogic; 47 from testmanager.core.schedgroup import SchedGroupLogic, SchedGroupData; 48 from testmanager.core.testbox import TestBoxLogic, TestBoxData; 49 from testmanager.core.testcase import TestCaseLogic, TestCaseData; 50 from testmanager.core.testgroup import TestGroupLogic, TestGroupData; 51 from testmanager.core.testset import TestSetData; 52 from testmanager.core.useraccount import UserAccountLogic, UserAccountData; 37 53 38 54 … … 45 61 WuiListContentBase.__init__(self, aoEntries, iPage, cItemsPerPage, tsEffective, 'System Changelog', 46 62 fnDPrint = fnDPrint, oDisp = oDisp); 47 self._asColumnHeaders = ['Date', 'Author', 'What', 'Description']; 48 self._asColumnAttribs = ['', '', '', '']; 63 self._asColumnHeaders = [ 'When', 'User', 'Event', 'Details' ]; 64 self._asColumnAttribs = [ 'align="center"', 'align="center"', '', '' ]; 65 self._oBuildBlacklistLogic = BuildBlacklistLogic(oDisp.getDb()); 66 self._oBuildLogic = BuildLogic(oDisp.getDb()); 67 self._oBuildSourceLogic = BuildSourceLogic(oDisp.getDb()); 68 self._oFailureCategoryLogic = FailureCategoryLogic(oDisp.getDb()); 69 self._oFailureReasonLogic = FailureReasonLogic(oDisp.getDb()); 70 self._oGlobalResourceLogic = GlobalResourceLogic(oDisp.getDb()); 71 self._oSchedGroupLogic = SchedGroupLogic(oDisp.getDb()); 72 self._oTestBoxLogic = TestBoxLogic(oDisp.getDb()); 73 self._oTestCaseLogic = TestCaseLogic(oDisp.getDb()); 74 self._oTestGroupLogic = TestGroupLogic(oDisp.getDb()); 75 self._oUserAccountLogic = UserAccountLogic(oDisp.getDb()); 76 self._sPrevDate = ''; 49 77 _ = cDaysBack; 50 78 51 def _formatListEntry(self, iEntry): 52 from testmanager.webui.wuiadmin import WuiAdmin; 53 oEntry = self._aoEntries[iEntry]; 54 55 return [ 56 oEntry.tsEffective, 57 oEntry.oAuthor.sUsername if oEntry.oAuthor is not None else '', 58 '%s(%s)' % (oEntry.sWhat, oEntry.idWhat,), 59 oEntry.sDesc, 60 ]; 61 62 79 # oDetails = self._createBlacklistingDetailsLink(oEntry.idWhat, oEntry.tsEffective); 80 def _createBlacklistingDetailsLink(self, idBlacklisting, tsEffective): 81 """ Creates a link to the build source details. """ 82 oBlacklisting = self._oBuildBlacklistLogic.cachedLookup(idBlacklisting); 83 if oBlacklisting is not None: 84 from testmanager.webui.wuiadmin import WuiAdmin; 85 return WuiAdminLink('Blacklisting #%u' % (oBlacklisting.idBlacklisting,), 86 WuiAdmin.ksActionBuildBlacklistDetails, tsEffective, 87 { BuildBlacklistData.ksParam_idBlacklisting: oBlacklisting.idBlacklisting }, 88 fBracketed = False); 89 return WuiElementText('[blacklisting #%u not found]' % (idBlacklisting,)); 90 91 def _createBuildDetailsLink(self, idBuild, tsEffective): 92 """ Creates a link to the build details. """ 93 oBuild = self._oBuildLogic.cachedLookup(idBuild); 94 if oBuild is not None: 95 from testmanager.webui.wuiadmin import WuiAdmin; 96 return WuiAdminLink('%s %sr%u' % ( oBuild.oCat.sProduct, oBuild.sVersion, oBuild.iRevision), 97 WuiAdmin.ksActionBuildDetails, tsEffective, 98 { BuildData.ksParam_idBuild: oBuild.idBuild }, 99 fBracketed = False, 100 sTitle = 'build #%u for %s, type %s' 101 % (oBuild.idBuild, ' & '.join(oBuild.oCat.asOsArches), oBuild.oCat.sType)); 102 return WuiElementText('[build #%u not found]' % (idBuild,)); 103 104 def _createBuildSourceDetailsLink(self, idBuildSrc, tsEffective): 105 """ Creates a link to the build source details. """ 106 oBuildSource = self._oBuildSourceLogic.cachedLookup(idBuildSrc); 107 if oBuildSource is not None: 108 from testmanager.webui.wuiadmin import WuiAdmin; 109 return WuiAdminLink(oBuildSource.sName, WuiAdmin.ksActionBuildSrcDetails, tsEffective, 110 { BuildSourceData.ksParam_idBuildSrc: oBuildSource.idBuildSrc }, 111 fBracketed = False, 112 sTitle = 'Build source #%u' % (oBuildSource.idBuildSrc,)); 113 return WuiElementText('[build source #%u not found]' % (idBuildSrc,)); 114 115 def _createFailureCategoryDetailsLink(self, idFailureCategory, tsEffective): 116 """ Creates a link to the failure category details. """ 117 oFailureCategory = self._oFailureCategoryLogic.cachedLookup(idFailureCategory); 118 if oFailureCategory is not None: 119 from testmanager.webui.wuiadmin import WuiAdmin; 120 return WuiAdminLink(oFailureCategory.sShort, WuiAdmin.ksActionFailureCategoryDetails, tsEffective, 121 { FailureCategoryData.ksParam_idFailureCategory: oFailureCategory.idFailureCategory }, 122 fBracketed = False, 123 sTitle = 'Failure category #%u' % (oFailureCategory.idFailureCategory,)); 124 return WuiElementText('[failure category #%u not found]' % (idFailureCategory,)); 125 126 def _createFailureReasonDetailsLink(self, idFailureReason, tsEffective): 127 """ Creates a link to the failure reason details. """ 128 oFailureReason = self._oFailureReasonLogic.cachedLookup(idFailureReason); 129 if oFailureReason is not None: 130 from testmanager.webui.wuiadmin import WuiAdmin; 131 return WuiAdminLink(oFailureReason.sShort, WuiAdmin.ksActionFailureReasonDetails, tsEffective, 132 { FailureReasonData.ksParam_idFailureReason: oFailureReason.idFailureReason }, 133 fBracketed = False, 134 sTitle = 'Failure reason #%u, category %s' 135 % (oFailureReason.idFailureReason, oFailureReason.oCategory.sShort)); 136 return WuiElementText('[failure reason #%u not found]' % (idFailureReason,)); 137 138 def _createGlobalResourceDetailsLink(self, idGlobalRsrc, tsEffective): 139 """ Creates a link to the global resource details. """ 140 oGlobalResource = self._oGlobalResourceLogic.cachedLookup(idGlobalRsrc); 141 if oGlobalResource is not None: 142 from testmanager.webui.wuiadmin import WuiAdmin; 143 return WuiAdminLink(oGlobalResource.sName, '@todo', tsEffective, 144 { GlobalResourceData.ksParam_idGlobalRsrc: oGlobalResource.idGlobalRsrc }, 145 fBracketed = False, 146 sTitle = 'Global resource #%u' % (oGlobalResource.idGlobalRsrc,)); 147 return WuiElementText('[global resource #%u not found]' % (idGlobalRsrc,)); 148 149 def _createSchedGroupDetailsLink(self, idSchedGroup, tsEffective): 150 """ Creates a link to the scheduling group details. """ 151 oSchedGroup = self._oSchedGroupLogic.cachedLookup(idSchedGroup); 152 if oSchedGroup is not None: 153 from testmanager.webui.wuiadmin import WuiAdmin; 154 return WuiAdminLink(oSchedGroup.sName, WuiAdmin.ksActionSchedGroupDetails, tsEffective, 155 { SchedGroupData.ksParam_idSchedGroup: oSchedGroup.idSchedGroup }, 156 fBracketed = False, 157 sTitle = 'Scheduling group #%u' % (oSchedGroup.idSchedGroup,)); 158 return WuiElementText('[scheduling group #%u not found]' % (idSchedGroup,)); 159 160 def _createTestBoxDetailsLink(self, idTestBox, tsEffective): 161 """ Creates a link to the testbox details. """ 162 oTestBox = self._oTestBoxLogic.cachedLookup(idTestBox); 163 if oTestBox is not None: 164 from testmanager.webui.wuiadmin import WuiAdmin; 165 return WuiAdminLink(oTestBox.sName, WuiAdmin.ksActionTestBoxDetails, tsEffective, 166 { TestBoxData.ksParam_idTestBox: oTestBox.idTestBox }, 167 fBracketed = False, sTitle = 'Testbox #%u' % (oTestBox.idTestBox,)); 168 return WuiElementText('[testbox #%u not found]' % (idTestBox,)); 169 170 def _createTestCaseDetailsLink(self, idTestCase, tsEffective): 171 """ Creates a link to the test case details. """ 172 oTestCase = self._oTestCaseLogic.cachedLookup(idTestCase); 173 if oTestCase is not None: 174 from testmanager.webui.wuiadmin import WuiAdmin; 175 return WuiAdminLink(oTestCase.sName, WuiAdmin.ksActionTestCaseDetails, tsEffective, 176 { TestCaseData.ksParam_idTestCase: oTestCase.idTestCase }, 177 fBracketed = False, sTitle = 'Test case #%u' % (oTestCase.idTestCase,)); 178 return WuiElementText('[test case #%u not found]' % (idTestCase,)); 179 180 def _createTestGroupDetailsLink(self, idTestGroup, tsEffective): 181 """ Creates a link to the test group details. """ 182 oTestGroup = self._oTestGroupLogic.cachedLookup(idTestGroup); 183 if oTestGroup is not None: 184 from testmanager.webui.wuiadmin import WuiAdmin; 185 return WuiAdminLink(oTestGroup.sName, WuiAdmin.ksActionTestGroupDetails, tsEffective, 186 { TestGroupData.ksParam_idTestGroup: oTestGroup.idTestGroup }, 187 fBracketed = False, sTitle = 'Test group #%u' % (oTestGroup.idTestGroup,)); 188 return WuiElementText('[test group #%u not found]' % (idTestGroup,)); 189 190 def _createTestSetResultsDetailsLink(self, idTestSet, tsEffective): 191 """ Creates a link to the test set results. """ 192 _ = tsEffective; 193 from testmanager.webui.wuimain import WuiMain; 194 return WuiMainLink('test set #%u' % idTestSet, WuiMain.ksActionTestSetDetails, 195 { TestSetData.ksParam_idTestSet: idTestSet }, fBracketed = False); 196 197 def _createTestSetDetailsLinkByResult(self, idTestResult, tsEffective): 198 """ Creates a link to the test set results. """ 199 _ = tsEffective; 200 from testmanager.webui.wuimain import WuiMain; 201 return WuiMainLink('test result #%u' % idTestResult, WuiMain.ksActionTestSetDetailsFromResult, 202 { TestSetData.ksParam_idTestResult: idTestResult }, fBracketed = False); 203 204 def _createUserAccountDetailsLink(self, uid, tsEffective): 205 """ Creates a link to the user account details. """ 206 oUser = self._oUserAccountLogic.cachedLookup(uid); 207 if oUser is not None: 208 from testmanager.webui.wuiadmin import WuiAdmin; 209 return WuiAdminLink(oUser.sUsername, '@todo', tsEffective, { UserAccountData.ksParam_uid: oUser.uid }, 210 fBracketed = False, sTitle = '%s (#%u)' % (oUser.sFullName, oUser.uid)); 211 return WuiElementText('[user #%u not found]' % (uid,)); 212 213 def _formatDescGeneric(self, sDesc, oEntry): 214 """ 215 Generically format system log the description. 216 """ 217 oRet = WuiHtmlKeeper(); 218 asWords = sDesc.split(); 219 for sWord in asWords: 220 offEqual = sWord.find('='); 221 if offEqual > 0: 222 sKey = sWord[:offEqual]; 223 try: idValue = int(sWord[offEqual+1:].rstrip('.,')); 224 except: pass; 225 else: 226 if sKey == 'idTestSet': 227 oRet.append(self._createTestSetResultsDetailsLink(idValue, oEntry.tsEffective)); 228 continue; 229 if sKey == 'idTestBox': 230 oRet.append(self._createTestBoxDetailsLink(idValue, oEntry.tsEffective)); 231 continue; 232 if sKey == 'idSchedGroup': 233 oRet.append(self._createSchedGroupDetailsLink(idValue, oEntry.tsEffective)); 234 continue; 235 236 oRet.append(WuiElementText(sWord)); 237 return oRet; 238 239 def _formatListEntryHtml(self, iEntry): 240 """ 241 Overridden parent method. 242 """ 243 oEntry = self._aoEntries[iEntry]; 244 245 # 246 # Format the timestamp. 247 # 248 sDate = self.formatTsShort(oEntry.tsEffective); 249 if sDate[:10] == self._sPrevDate: 250 sDate = sDate[11:] 251 else: 252 self._sPrevDate = sDate[:10]; 253 sDate = '<b>' + sDate[:10] + '</b><br>' + sDate[11:]; 254 255 # 256 # System log events. 257 # pylint: disable=redefined-variable-type 258 # 259 aoChanges = None; 260 if oEntry.sEvent == SystemLogData.ksEvent_CmdNacked: 261 sEvent = 'Command not acknowleged'; 262 oDetails = oEntry.sDesc; 263 264 elif oEntry.sEvent == SystemLogData.ksEvent_TestBoxUnknown: 265 sEvent = 'Unknown testbox'; 266 oDetails = oEntry.sDesc; 267 268 elif oEntry.sEvent == SystemLogData.ksEvent_TestSetAbandoned: 269 sEvent = 'Abandoned test set'; 270 oDetails = self._formatDescGeneric(oEntry.sDesc, oEntry); 271 272 elif oEntry.sEvent == SystemLogData.ksEvent_UserAccountUnknown: 273 sEvent = 'Unknown user account'; 274 oDetails = oEntry.sDesc; 275 276 elif oEntry.sEvent == SystemLogData.ksEvent_XmlResultMalformed: 277 sEvent = 'Malformed XML result'; 278 oDetails = oEntry.sDesc; 279 280 elif oEntry.sEvent == SystemLogData.ksEvent_SchedQueueRecreate: 281 sEvent = 'Recreating scheduling queue'; 282 asWords = oEntry.sDesc.split(); 283 if len(asWords) > 3 and asWords[0] == 'User' and asWords[1][0] == '#': 284 try: idAuthor = int(asWords[1][1:]); 285 except: pass; 286 else: 287 oEntry.oAuthor = self._oUserAccountLogic.cachedLookup(idAuthor); 288 if oEntry.oAuthor is not None: 289 i = 2; 290 if asWords[i] == 'recreated': i += 1; 291 oEntry.sDesc = ' '.join(asWords[i:]); 292 oDetails = self._formatDescGeneric(oEntry.sDesc.replace('sched queue #', 'for scheduling group idSchedGroup='), 293 oEntry); 294 # 295 # System changelog events. 296 # 297 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_Blacklisting: 298 sEvent = 'Modified blacklisting'; 299 oDetails = self._createBlacklistingDetailsLink(oEntry.idWhat, oEntry.tsEffective); 300 301 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_Build: 302 sEvent = 'Modified build'; 303 oDetails = self._createBuildDetailsLink(oEntry.idWhat, oEntry.tsEffective); 304 305 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_BuildSource: 306 sEvent = 'Modified build source'; 307 oDetails = self._createBuildSourceDetailsLink(oEntry.idWhat, oEntry.tsEffective); 308 309 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_GlobalRsrc: 310 sEvent = 'Modified global resource'; 311 oDetails = self._createGlobalResourceDetailsLink(oEntry.idWhat, oEntry.tsEffective); 312 313 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_FailureCategory: 314 sEvent = 'Modified failure category'; 315 oDetails = self._createFailureCategoryDetailsLink(oEntry.idWhat, oEntry.tsEffective); 316 (aoChanges, _) = self._oFailureCategoryLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); 317 318 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_FailureReason: 319 sEvent = 'Modified failure reason'; 320 oDetails = self._createFailureReasonDetailsLink(oEntry.idWhat, oEntry.tsEffective); 321 (aoChanges, _) = self._oFailureReasonLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); 322 323 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_SchedGroup: 324 sEvent = 'Modified scheduling group'; 325 oDetails = self._createSchedGroupDetailsLink(oEntry.idWhat, oEntry.tsEffective); 326 327 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestBox: 328 sEvent = 'Modified testbox'; 329 oDetails = self._createTestBoxDetailsLink(oEntry.idWhat, oEntry.tsEffective); 330 (aoChanges, _) = self._oTestBoxLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); 331 332 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestCase: 333 sEvent = 'Modified test case'; 334 oDetails = self._createTestCaseDetailsLink(oEntry.idWhat, oEntry.tsEffective); 335 (aoChanges, _) = self._oTestCaseLogic.fetchForChangeLog(oEntry.idWhat, 0, 1, oEntry.tsEffective); 336 337 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestGroup: 338 sEvent = 'Modified test group'; 339 oDetails = self._createTestGroupDetailsLink(oEntry.idWhat, oEntry.tsEffective); 340 341 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_TestResult: 342 sEvent = 'Modified test failure reason'; 343 oDetails = self._createTestSetDetailsLinkByResult(oEntry.idWhat, oEntry.tsEffective); 344 345 elif oEntry.sEvent == SystemChangelogLogic.ksWhat_User: 346 sEvent = 'Modified user account'; 347 oDetails = self._createUserAccountDetailsLink(oEntry.idWhat, oEntry.tsEffective); 348 349 else: 350 sEvent = '%s(%s)' % (oEntry.sEvent, oEntry.idWhat,); 351 oDetails = '!Unknown event!' + (oEntry.sDesc if oEntry.sDesc else ''); 352 353 # 354 # Do the formatting. 355 # 356 sRowClass = 'tmodd' if (iEntry + 1) & 1 else 'tmeven'; 357 358 if aoChanges is not None and len(aoChanges) > 0: 359 oChangeEntry = aoChanges[0]; 360 cAttribsChanged = len(oChangeEntry.aoChanges) + 1; 361 else: 362 oChangeEntry = None; 363 cAttribsChanged = 1; 364 365 sHtml = u' <tr class="%s">\n' \ 366 u' <td rowspan="%d">%s</td>\n' \ 367 u' <td rowspan="%d">%s</td>\n' \ 368 u' <td rowspan="%d">%s</td>\n' \ 369 u' <td colspan="3">%s</td>\n' \ 370 u' </tr>\n' \ 371 % ( sRowClass, 372 cAttribsChanged, sDate, 373 cAttribsChanged, webutils.escapeElem(oEntry.oAuthor.sUsername if oEntry.oAuthor is not None else ''), 374 cAttribsChanged, webutils.escapeElem(sEvent), 375 oDetails.toHtml() if isinstance(oDetails, WuiHtmlBase) else oDetails, 376 ); 377 378 if oChangeEntry is not None: 379 for j, oChange in enumerate(oChangeEntry.aoChanges): 380 if isinstance(oChange, AttributeChangeEntryPre): 381 sHtml += ' <tr class="%s%s tmsyschlogattr"><td>%s</td>'\ 382 '<td><div class="tdpre"><pre>%s</pre></div></td>' \ 383 '<td><div class="tdpre"><pre>%s</pre></div></td></tr>\n' \ 384 % ( sRowClass, 'odd' if j & 1 else 'even', 385 webutils.escapeElem(oChange.sAttr), 386 webutils.escapeElem(oChange.sOldText), 387 webutils.escapeElem(oChange.sNewText), ); 388 else: 389 sHtml += ' <tr class="%s%s tmsyschlogattr"><td>%s</td><td>%s</td><td>%s</td></tr>\n' \ 390 % ( sRowClass, 'odd' if j & 1 else 'even', 391 webutils.escapeElem(oChange.sAttr), 392 webutils.escapeElem(oChange.sOldText), 393 webutils.escapeElem(oChange.sNewText), ); 394 sHtml += u' </tr>\n' 395 return sHtml; 396 397 398 def _generateTableHeaders(self): 399 """ 400 Overridden parent method. 401 """ 402 403 sHtml = u'<thead class="tmheader">\n' \ 404 u' <tr>\n' \ 405 u' <th rowspan="2">When</th>\n' \ 406 u' <th rowspan="2">Who</th>\n' \ 407 u' <th rowspan="2">Event</th>\n' \ 408 u' <th colspan="3">Details</th>\n' \ 409 u' </tr>\n' \ 410 u' <tr>\n' \ 411 u' <th>Attribute</th>\n' \ 412 u' <th>Old Value</th>\n' \ 413 u' <th>New Value</th>\n' \ 414 u' </tr>\n' \ 415 u'</thead>\n'; 416 return sHtml; 417 -
trunk/src/VBox/ValidationKit/testmanager/webui/wuicontentbase.py
r65039 r65040 111 111 return sFmt % (sExtraAttrs, webutils.escapeAttr(self.sUrl), webutils.escapeElem(self.sName)); 112 112 113 113 114 class WuiTmLink(WuiLinkBase): # pylint: disable=R0903 114 115 """ Local link to the test manager. """ … … 132 133 133 134 135 class WuiAdminLink(WuiTmLink): # pylint: disable=R0903 136 """ Local link to the test manager's admin portion. """ 137 138 def __init__(self, sName, sAction, tsEffectiveDate = None, dParams = None, sConfirm = None, sTitle = None, 139 sFragmentId = None, fBracketed = True): 140 from testmanager.webui.wuiadmin import WuiAdmin; 141 if dParams is None or len(dParams) == 0: 142 dParams = dict(); 143 else: 144 dParams = dict(dParams); 145 if sAction is not None: 146 dParams[WuiAdmin.ksParamAction] = sAction; 147 if tsEffectiveDate is not None: 148 dParams[WuiAdmin.ksParamEffectiveDate] = tsEffectiveDate; 149 WuiTmLink.__init__(self, sName, WuiAdmin.ksScriptName, dParams = dParams, sConfirm = sConfirm, sTitle = sTitle, 150 sFragmentId = sFragmentId, fBracketed = fBracketed); 151 152 class WuiMainLink(WuiTmLink): # pylint: disable=R0903 153 """ Local link to the test manager's main portion. """ 154 155 def __init__(self, sName, sAction, dParams = None, sConfirm = None, sTitle = None, 156 sFragmentId = None, fBracketed = True): 157 from testmanager.webui.wuimain import WuiMain; 158 if dParams is None or len(dParams) == 0: 159 dParams = dict(); 160 else: 161 dParams = dict(dParams); 162 if sAction is not None: 163 dParams[WuiMain.ksParamAction] = sAction; 164 WuiTmLink.__init__(self, sName, WuiMain.ksScriptName, dParams = dParams, sConfirm = sConfirm, sTitle = sTitle, 165 sFragmentId = sFragmentId, fBracketed = fBracketed); 166 134 167 class WuiSvnLink(WuiLinkBase): # pylint: disable=R0903 135 168 """ … … 214 247 % ( webutils.escapeAttr(sSpanClass), webutils.escapeAttr(sTitle), webutils.escapeElem(sText),)); 215 248 249 class WuiElementText(WuiRawHtml): # pylint: disable=R0903 250 """ 251 Outputs the given element text. 252 """ 253 def __init__(self, sText): 254 WuiRawHtml.__init__(self, webutils.escapeElem(sText)); 216 255 217 256 … … 254 293 self._fnDPrint(sText); 255 294 256 def formatTsShort(self, oTs): 295 @staticmethod 296 def formatTsShort(oTs): 257 297 """ 258 298 Formats a timestamp (db rep) into a short form. … … 399 439 return []; 400 440 401 def _calcChangeLogEntryLinks(self, aoEntries, iEntry): 441 @staticmethod 442 def _calcChangeLogEntryLinks(aoEntries, iEntry): 402 443 """ 403 444 Returns an array of links to go with the change log entry. … … 410 451 return []; 411 452 412 def _guessChangeLogEntryDescription(self, aoEntries, iEntry): 453 @staticmethod 454 def _guessChangeLogEntryDescription(aoEntries, iEntry): 413 455 """ 414 456 Guesses the action + author that caused the change log entry. … … 435 477 return 'Modified by %s.' % (sAuthor,); 436 478 437 def _formatChangeLogEntry(self, aoEntries, iEntry): 479 @staticmethod 480 def formatChangeLogEntry(aoEntries, iEntry): 438 481 """ 439 482 Formats one change log entry into one or more HTML table rows. … … 453 496 ' </tr>\n' \ 454 497 % ( sRowClass, 455 len(oEntry.aoChanges) + 1, webutils.escapeElem( self.formatTsShort(oEntry.tsEffective)),456 len(oEntry.aoChanges) + 1, webutils.escapeElem( self.formatTsShort(oEntry.tsExpire)),457 self._guessChangeLogEntryDescription(aoEntries, iEntry),458 ' '.join(oLink.toHtml() for oLink in self._calcChangeLogEntryLinks(aoEntries, iEntry)),);498 len(oEntry.aoChanges) + 1, webutils.escapeElem(WuiFormContentBase.formatTsShort(oEntry.tsEffective)), 499 len(oEntry.aoChanges) + 1, webutils.escapeElem(WuiFormContentBase.formatTsShort(oEntry.tsExpire)), 500 WuiFormContentBase._guessChangeLogEntryDescription(aoEntries, iEntry), 501 ' '.join(oLink.toHtml() for oLink in WuiFormContentBase._calcChangeLogEntryLinks(aoEntries, iEntry)),); 459 502 460 503 # Additional rows for each changed attribute. … … 574 617 ' <tbody>\n'; 575 618 576 for iEntry in range(len(aoEntries)):577 sContent += self. _formatChangeLogEntry(aoEntries, iEntry);619 for iEntry, _ in enumerate(aoEntries): 620 sContent += self.formatChangeLogEntry(aoEntries, iEntry); 578 621 579 622 sContent += ' <tbody>\n' \ … … 894 937 return sNavigation; 895 938 939 def _generateTableHeaders(self): 940 """ 941 Generate table headers. 942 Returns raw html string. 943 Overridable. 944 """ 945 946 sHtml = ' <thead class="tmheader"><tr>'; 947 for oHeader in self._asColumnHeaders: 948 if isinstance(oHeader, WuiHtmlBase): 949 sHtml += '<th>' + oHeader.toHtml() + '</th>'; 950 else: 951 sHtml += '<th>' + webutils.escapeElem(oHeader) + '</th>'; 952 sHtml += '</tr><thead>\n'; 953 return sHtml 954 896 955 def _generateTable(self): 897 956 """ … … 910 969 self._asColumnHeaders = self._aoEntries[0].getDataAttributes(); 911 970 912 sPageBody += ' <thead class="tmheader"><tr>'; 913 for oHeader in self._asColumnHeaders: 914 if isinstance(oHeader, WuiHtmlBase): 915 sPageBody += '<th>' + oHeader.toHtml() + '</th>'; 916 else: 917 sPageBody += '<th>' + webutils.escapeElem(oHeader) + '</th>'; 918 sPageBody += '</tr><thead>\n'; 971 sPageBody += self._generateTableHeaders(); 919 972 920 973 #
Note:
See TracChangeset
for help on using the changeset viewer.