# -*- coding: utf-8 -*- # $Id: wuihlpform.py $ """ Test Manager Web-UI - Form Helpers. """ __copyright__ = \ """ Copyright (C) 2012-2023 Oracle and/or its affiliates. This file is part of VirtualBox base platform packages, as available from https://www.virtualbox.org. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, in version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . The contents of this file may alternatively be used under the terms of the Common Development and Distribution License Version 1.0 (CDDL), a copy of it is provided in the "COPYING.CDDL" file included in the VirtualBox distribution, in which case the provisions of the CDDL are applicable instead of those of the GPL. You may elect to license modified versions of this file under the terms and conditions of either the GPL or the CDDL or both. SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 """ __version__ = "$Revision: 155244 $" # Standard python imports. import copy; import sys; # Validation Kit imports. from common import utils; from common.webutils import escapeAttr, escapeElem; from testmanager import config; from testmanager.core.schedgroup import SchedGroupMemberData, SchedGroupDataEx; from testmanager.core.testcaseargs import TestCaseArgsData; from testmanager.core.testgroup import TestGroupMemberData, TestGroupDataEx; from testmanager.core.testbox import TestBoxDataForSchedGroup; # Python 3 hacks: if sys.version_info[0] >= 3: unicode = str; # pylint: disable=redefined-builtin,invalid-name class WuiHlpForm(object): """ Helper for constructing a form. """ ksItemsList = 'ksItemsList' ksOnSubmit_AddReturnToFieldWithCurrentUrl = '+AddReturnToFieldWithCurrentUrl+'; def __init__(self, sId, sAction, dErrors = None, fReadOnly = False, sOnSubmit = None): self._fFinalized = False; self._fReadOnly = fReadOnly; self._dErrors = dErrors if dErrors is not None else {}; if sOnSubmit == self.ksOnSubmit_AddReturnToFieldWithCurrentUrl: sOnSubmit = u'return addRedirectToInputFieldWithCurrentUrl(this)'; if sOnSubmit is None: sOnSubmit = u''; else: sOnSubmit = u' onsubmit=\"%s\"' % (escapeAttr(sOnSubmit),); self._sBody = u'\n' \ u'
\n' \ u'
\n' \ u'
    \n' \ % (sId, sAction, sOnSubmit); def _add(self, sText): """Internal worker for appending text to the body.""" assert not self._fFinalized; if not self._fFinalized: self._sBody += utils.toUnicode(sText, errors='ignore'); return True; return False; def _escapeErrorText(self, sText): """Escapes error text, preserving some predefined HTML tags.""" if sText.find('
    ') >= 0: asParts = sText.split('
    '); for i, _ in enumerate(asParts): asParts[i] = escapeElem(asParts[i].strip()); sText = '
    \n'.join(asParts); else: sText = escapeElem(sText); return sText; def _addLabel(self, sName, sLabel, sDivSubClass = 'normal'): """Internal worker for adding a label.""" if sName in self._dErrors: sError = self._dErrors[sName]; if utils.isString(sError): # List error trick (it's an associative array). return self._add(u'
  • \n' u'
    \n' u' \n' % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel), self._escapeErrorText(sError), ) ); return self._add(u'
  • \n' u'
    \n' u' \n' % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel)) ); def finalize(self): """ Finalizes the form and returns the body. """ if not self._fFinalized: self._add(u'
\n' u'
\n' u'
\n' u'
\n' ); return self._sBody; def addTextHidden(self, sName, sValue, sExtraAttribs = ''): """Adds a hidden text input.""" return self._add(u'
\n' u' \n' u'
\n' u' \n' % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(str(sValue)) )); # # Non-input stuff. # def addNonText(self, sValue, sLabel, sName = 'non-text', sPostHtml = ''): """Adds a read-only text input.""" self._addLabel(sName, sLabel, 'string'); if sValue is None: sValue = ''; return self._add(u'

%s%s

\n' u' \n' u' \n' % (escapeElem(unicode(sValue)), sPostHtml )); def addRawHtml(self, sRawHtml, sLabel, sName = 'raw-html'): """Adds a read-only text input.""" self._addLabel(sName, sLabel, 'string'); self._add(sRawHtml); return self._add(u' \n' u' \n'); # # Text input fields. # def addText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''): """Adds a text input.""" if self._fReadOnly: return self.addTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs); if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass); self._addLabel(sName, sLabel, sSubClass); if sValue is None: sValue = ''; return self._add(u' %s\n' u' \n' u' \n' % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeAttr(unicode(sValue)), sPostHtml )); def addTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''): """Adds a read-only text input.""" if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass); self._addLabel(sName, sLabel, sSubClass); if sValue is None: sValue = ''; return self._add(u' ' u'%s\n' u' \n' u' \n' % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeAttr(unicode(sValue)), sPostHtml )); def addWideText(self, sName, sValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds a wide text input.""" return self.addText(sName, sValue, sLabel, 'wide', sExtraAttribs, sPostHtml = sPostHtml); def addWideTextRO(self, sName, sValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds a wide read-only text input.""" return self.addTextRO(sName, sValue, sLabel, 'wide', sExtraAttribs, sPostHtml = sPostHtml); def _adjustMultilineTextAttribs(self, sExtraAttribs, sValue): """ Internal helper for setting good default sizes for textarea based on content.""" if sExtraAttribs.find('cols') < 0 and sExtraAttribs.find('width') < 0: sExtraAttribs = 'cols="96%" ' + sExtraAttribs; if sExtraAttribs.find('rows') < 0 and sExtraAttribs.find('width') < 0: if sValue is None: sValue = ''; else: sValue = sValue.strip(); cRows = sValue.count('\n') + (not sValue.endswith('\n')); if cRows * 80 < len(sValue): cRows += 2; cRows = max(min(cRows, 16), 2); sExtraAttribs = ('rows="%s" ' % (cRows,)) + sExtraAttribs; return sExtraAttribs; def addMultilineText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''): """Adds a multiline text input.""" if self._fReadOnly: return self.addMultilineTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs); if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass) self._addLabel(sName, sLabel, sSubClass) if sValue is None: sValue = ''; sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue) return self._add(u' \n' u' \n' u' \n' % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue), escapeElem(sNewValue))) def addMultilineTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''): """Adds a multiline read-only text input.""" if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass) self._addLabel(sName, sLabel, sSubClass) if sValue is None: sValue = ''; sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue) return self._add(u' \n' u' \n' u' \n' % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue), escapeElem(sNewValue))) def addInt(self, sName, iValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds an integer input.""" return self.addText(sName, unicode(iValue), sLabel, 'int', sExtraAttribs, sPostHtml = sPostHtml); def addIntRO(self, sName, iValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds an integer input.""" return self.addTextRO(sName, unicode(iValue), sLabel, 'int', sExtraAttribs, sPostHtml = sPostHtml); def addLong(self, sName, lValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds a long input.""" return self.addText(sName, unicode(lValue), sLabel, 'long', sExtraAttribs, sPostHtml = sPostHtml); def addLongRO(self, sName, lValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds a long input.""" return self.addTextRO(sName, unicode(lValue), sLabel, 'long', sExtraAttribs, sPostHtml = sPostHtml); def addUuid(self, sName, uuidValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds an UUID input.""" return self.addText(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs, sPostHtml = sPostHtml); def addUuidRO(self, sName, uuidValue, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds a read-only UUID input.""" return self.addTextRO(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs, sPostHtml = sPostHtml); def addTimestampRO(self, sName, sTimestamp, sLabel, sExtraAttribs = '', sPostHtml = ''): """Adds a read-only database string timstamp input.""" return self.addTextRO(sName, sTimestamp, sLabel, 'timestamp', sExtraAttribs, sPostHtml = sPostHtml); # # Text areas. # # # Combo boxes. # def addComboBox(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''): """Adds a combo box.""" if self._fReadOnly: return self.addComboBoxRO(sName, sSelected, sLabel, aoOptions, sExtraAttribs, sPostHtml); self._addLabel(sName, sLabel, 'combobox'); self._add(' ' + sPostHtml + '\n' u' \n' u' \n'); def addComboBoxRO(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''): """Adds a read-only combo box.""" self.addTextHidden(sName, sSelected); self._addLabel(sName, sLabel, 'combobox-readonly'); self._add(u' ' + sPostHtml + '\n' u' \n' u' \n'); # # Check boxes. # @staticmethod def _reinterpretBool(fValue): """Reinterprets a value as a boolean type.""" if fValue is not type(True): if fValue is None: fValue = False; elif str(fValue) in ('True', 'true', '1'): fValue = True; else: fValue = False; return fValue; def addCheckBox(self, sName, fChecked, sLabel, sExtraAttribs = ''): """Adds an check box.""" if self._fReadOnly: return self.addCheckBoxRO(sName, fChecked, sLabel, sExtraAttribs); self._addLabel(sName, sLabel, 'checkbox'); fChecked = self._reinterpretBool(fChecked); return self._add(u' \n' u' \n' u' \n' % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs)); def addCheckBoxRO(self, sName, fChecked, sLabel, sExtraAttribs = ''): """Adds an readonly check box.""" self._addLabel(sName, sLabel, 'checkbox'); fChecked = self._reinterpretBool(fChecked); # Hack Alert! The onclick and onkeydown are for preventing editing and fake readonly/disabled. return self._add(u' \n' u' \n' u' \n' % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs)); # # List of items to check # def _addList(self, sName, aoRows, sLabel, fUseTable = False, sId = 'dummy', sExtraAttribs = ''): """ Adds a list of items to check. @param sName Name of HTML form element @param aoRows List of [sValue, fChecked, sName] sub-arrays. @param sLabel Label of HTML form element """ fReadOnly = self._fReadOnly; ## @todo add this as a parameter. if fReadOnly: sExtraAttribs += ' readonly onclick="return false" onkeydown="return false"'; self._addLabel(sName, sLabel, 'list'); if not aoRows: return self._add('No items') sNameEscaped = escapeAttr(sName); self._add('
\n' % (escapeAttr(sId),)); if fUseTable: self._add(' \n'); for asRow in aoRows: assert len(asRow) == 3; # Don't allow sloppy input data! fChecked = self._reinterpretBool(asRow[1]) self._add(u' \n' u' \n' u' \n' u' \n' % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs, escapeElem(unicode(asRow[2])), )); self._add(u'
%s
\n'); else: for asRow in aoRows: assert len(asRow) == 3; # Don't allow sloppy input data! fChecked = self._reinterpretBool(asRow[1]) self._add(u'
' u' %s
\n' % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs, escapeElem(unicode(asRow[2])),)); return self._add(u'
\n' u' \n'); def addListOfOsArches(self, sName, aoOsArches, sLabel, sExtraAttribs = ''): """ List of checkboxes for OS/ARCH selection. asOsArches is a list of [sValue, fChecked, sName] sub-arrays. """ return self._addList(sName, aoOsArches, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-os-arches', sExtraAttribs = sExtraAttribs); def addListOfTypes(self, sName, aoTypes, sLabel, sExtraAttribs = ''): """ List of checkboxes for build type selection. aoTypes is a list of [sValue, fChecked, sName] sub-arrays. """ return self._addList(sName, aoTypes, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-build-types', sExtraAttribs = sExtraAttribs); def addListOfTestCases(self, sName, aoTestCases, sLabel, sExtraAttribs = ''): """ List of checkboxes for test box (dependency) selection. aoTestCases is a list of [sValue, fChecked, sName] sub-arrays. """ return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testcases', sExtraAttribs = sExtraAttribs); def addListOfResources(self, sName, aoTestCases, sLabel, sExtraAttribs = ''): """ List of checkboxes for resource selection. aoTestCases is a list of [sValue, fChecked, sName] sub-arrays. """ return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-resources', sExtraAttribs = sExtraAttribs); def addListOfTestGroups(self, sName, aoTestGroups, sLabel, sExtraAttribs = ''): """ List of checkboxes for test group selection. aoTestGroups is a list of [sValue, fChecked, sName] sub-arrays. """ return self._addList(sName, aoTestGroups, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testgroups', sExtraAttribs = sExtraAttribs); def addListOfTestCaseArgs(self, sName, aoVariations, sLabel): # pylint: disable=too-many-statements """ Adds a list of test case argument variations to the form. @param sName Name of HTML form element @param aoVariations List of TestCaseArgsData instances. @param sLabel Label of HTML form element """ self._addLabel(sName, sLabel); sTableId = u'TestArgsExtendingListRoot'; fReadOnly = self._fReadOnly; ## @todo argument? sReadOnlyAttr = u' readonly class="tmform-input-readonly"' if fReadOnly else ''; sHtml = u'
  • \n' # # Define javascript function for extending the list of test case # variations. Doing it here so we can use the python constants. This # also permits multiple argument lists on one page should that ever be # required... # if not fReadOnly: sHtml += u'\n'; # # List current entries. # sHtml += u'\n' \ % (sName, sName, ','.join(unicode(i) for i in range(len(aoVariations))), ); sHtml += u' \n' % (sTableId,) if not fReadOnly: sHtml += u' \n'; dSubErrors = {}; if sName in self._dErrors and isinstance(self._dErrors[sName], dict): dSubErrors = self._dErrors[sName]; for iVar, _ in enumerate(aoVariations): oVar = copy.copy(aoVariations[iVar]); oVar.convertToParamNull(); sHtml += u'\n' % (sName, iVar,) sHtml += u' \n' \ u' ' \ u' \n' \ u' ' \ u' \n' \ u' ' \ u' \n' \ % ( sName, iVar, TestCaseArgsData.ksParam_sSubName, sName, iVar, oVar.sSubName, sReadOnlyAttr, sName, iVar, TestCaseArgsData.ksParam_cGangMembers, sName, iVar, oVar.cGangMembers, sReadOnlyAttr, sName, iVar, TestCaseArgsData.ksParam_cSecTimeout, sName, iVar, utils.formatIntervalSeconds2(oVar.cSecTimeout), sReadOnlyAttr, ); if not fReadOnly: sHtml += u' \n' \ % (sName, iVar); else: sHtml += u' \n'; sHtml += u' \n' \ u' \n'; sHtml += u' \n' \ u' ' \ u' \n' \ u' \n' \ u' \n' \ % ( sName, iVar, TestCaseArgsData.ksParam_sArgs, sName, iVar, escapeAttr(oVar.sArgs), sReadOnlyAttr) sHtml += u' \n' \ u' ' \ u' \n' \ u' \n' \ u' \n' \ % ( sName, iVar, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName, iVar, escapeAttr(oVar.sTestBoxReqExpr), sReadOnlyAttr) sHtml += u' \n' \ u' ' \ u' \n' \ u' \n' \ u' \n' \ % ( sName, iVar, TestCaseArgsData.ksParam_sBuildReqExpr, sName, iVar, escapeAttr(oVar.sBuildReqExpr), sReadOnlyAttr) if iVar in dSubErrors: sHtml += u' \n' \ % (self._escapeErrorText(dSubErrors[iVar]),); sHtml += u'\n'; sHtml += u'
    \n' \ u' Add\n' % (sName,); if config.g_kfVBoxSpecific: sHtml += u' [Single CPU Variations\n' % (sName,); sHtml += u' amd64]\n' % (sName,); sHtml += u' [SMP Variations]\n' % (sName,); sHtml += u'
    Sub-name:Gang Members:Timeout:Remove
    Arguments:' \ u'
    TestBox Reqs:' \ u'
    Build Reqs:' \ u'

    %s

    \n' sHtml += u'
  • \n' return self._add(sHtml) def addListOfTestGroupMembers(self, sName, aoTestGroupMembers, aoAllTestCases, sLabel, # pylint: disable=too-many-locals fReadOnly = True): """ For WuiTestGroup. """ assert len(aoTestGroupMembers) <= len(aoAllTestCases); self._addLabel(sName, sLabel); if not aoAllTestCases: return self._add('
  • No testcases.
  • \n') self._add(u'\n' % ( TestGroupDataEx.ksParam_aidTestCases, ','.join([unicode(oTestCase.idTestCase) for oTestCase in aoAllTestCases]), )); self._add(u'\n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' ); if self._fReadOnly: fReadOnly = True; sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else ''; oDefMember = TestGroupMemberData(); aoTestGroupMembers = list(aoTestGroupMembers); # Copy it so we can pop. for iTestCase, _ in enumerate(aoAllTestCases): oTestCase = aoAllTestCases[iTestCase]; # Is it a member? oMember = None; for i, _ in enumerate(aoTestGroupMembers): if aoTestGroupMembers[i].oTestCase.idTestCase == oTestCase.idTestCase: oMember = aoTestGroupMembers.pop(i); break; # Start on the rows... sPrefix = u'%s[%d]' % (sName, oTestCase.idTestCase,); self._add(u' \n' u' \n' % ( 'tmodd' if iTestCase & 1 else 'tmeven', len(oTestCase.aoTestCaseArgs), sPrefix, TestGroupMemberData.ksParam_idTestCase, oTestCase.idTestCase, sPrefix, TestGroupMemberData.ksParam_idTestGroup, -1 if oMember is None else oMember.idTestGroup, sPrefix, TestGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire, sPrefix, TestGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective, sPrefix, TestGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor, TestGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr, oTestCase.idTestCase, oTestCase.idTestCase, escapeElem(oTestCase.sName), )); self._add(u' \n' % ( len(oTestCase.aoTestCaseArgs), escapeElem(oTestCase.sName), )); self._add(u' \n' % ( len(oTestCase.aoTestCaseArgs), sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs, ' checked' if oMember is None or oMember.aidTestCaseArgs is None else '', sCheckBoxAttr, )); self._add(u' \n' % ( len(oTestCase.aoTestCaseArgs), sPrefix, TestGroupMemberData.ksParam_iSchedPriority, (oMember if oMember is not None else oDefMember).iSchedPriority, ' readonly class="tmform-input-readonly"' if fReadOnly else '', )); # Argument variations. aidTestCaseArgs = [] if oMember is None or oMember.aidTestCaseArgs is None else oMember.aidTestCaseArgs; for iVar, oVar in enumerate(oTestCase.aoTestCaseArgs): if iVar > 0: self._add(' \n' % ('tmodd' if iTestCase & 1 else 'tmeven',)); self._add(u' \n' % ( sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs, ' checked' if oVar.idTestCaseArgs in aidTestCaseArgs else '', sCheckBoxAttr, oVar.idTestCaseArgs, )); self._add(u' \n' u' \n' u' \n' % ( oVar.cGangMembers, 'Default' if oVar.cSecTimeout is None else oVar.cSecTimeout, escapeElem(oVar.sArgs) )); self._add(u' \n'); if not oTestCase.aoTestCaseArgs: self._add(u' \n' u' \n'); return self._add(u' \n' u'
    Test CaseAll VarsPriority [0..31]Variations
    IncludedGang sizeTimeoutArguments
    \n' u' \n' # idTestCase u' \n' # idTestGroup u' \n' # tsExpire u' \n' # tsEffective u' \n' # uidAuthor u' \n' #(list) u' %s\n' u' \n' u' \n' u' \n' u'
    \n' u' ' u' %s%s%s
    \n'); def addListOfSchedGroupMembers(self, sName, aoSchedGroupMembers, aoAllRelevantTestGroups, # pylint: disable=too-many-locals sLabel, idSchedGroup, fReadOnly = True): """ For WuiAdminSchedGroup. """ if fReadOnly is None or self._fReadOnly: fReadOnly = self._fReadOnly; assert len(aoSchedGroupMembers) <= len(aoAllRelevantTestGroups); self._addLabel(sName, sLabel); if not aoAllRelevantTestGroups: return self._add(u'
  • No test groups.
  • \n') self._add(u'\n' % ( SchedGroupDataEx.ksParam_aidTestGroups, ','.join([unicode(oTestGroup.idTestGroup) for oTestGroup in aoAllRelevantTestGroups]), )); self._add(u'\n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' ); sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else ''; sComboBoxAttr = u' disabled' if fReadOnly else ''; oDefMember = SchedGroupMemberData(); aoSchedGroupMembers = list(aoSchedGroupMembers); # Copy it so we can pop. for iTestGroup, _ in enumerate(aoAllRelevantTestGroups): oTestGroup = aoAllRelevantTestGroups[iTestGroup]; # Is it a member? oMember = None; for i, _ in enumerate(aoSchedGroupMembers): if aoSchedGroupMembers[i].oTestGroup.idTestGroup == oTestGroup.idTestGroup: oMember = aoSchedGroupMembers.pop(i); break; # Start on the rows... sPrefix = u'%s[%d]' % (sName, oTestGroup.idTestGroup,); self._add(u' \n' u' \n' % ( 'tmodd' if iTestGroup & 1 else 'tmeven', sPrefix, SchedGroupMemberData.ksParam_idTestGroup, oTestGroup.idTestGroup, sPrefix, SchedGroupMemberData.ksParam_idSchedGroup, idSchedGroup, sPrefix, SchedGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire, sPrefix, SchedGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective, sPrefix, SchedGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor, SchedGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr, oTestGroup.idTestGroup, oTestGroup.idTestGroup, escapeElem(oTestGroup.sName), )); self._add(u' \n' % ( escapeElem(oTestGroup.sName), )); self._add(u' \n' % ( sPrefix, SchedGroupMemberData.ksParam_iSchedPriority, (oMember if oMember is not None else oDefMember).iSchedPriority, ' readonly class="tmform-input-readonly"' if fReadOnly else '', )); self._add(u' \n'); self._add(u' \n' % ( sPrefix, SchedGroupMemberData.ksParam_bmHourlySchedule, '' if oMember is None else oMember.bmHourlySchedule, )); self._add(u' \n'); return self._add(u' \n' u'
    Test GroupPriority [0..31]Prerequisite Test GroupWeekly schedule
    \n' u' \n' # idTestGroup u' \n' # idSchedGroup u' \n' # tsExpire u' \n' # tsEffective u' \n' # uidAuthor u' \n' #(list) u' %s\n' u' \n' u' \n' u' \n' u' \n' u' Todo\n' u'
    \n'); def addListOfSchedGroupBoxes(self, sName, aoSchedGroupBoxes, # pylint: disable=too-many-locals aoAllRelevantTestBoxes, sLabel, idSchedGroup, fReadOnly = True, fUseTable = False): # (str, list[TestBoxDataEx], list[TestBoxDataEx], str, bool, bool) -> str """ For WuiAdminSchedGroup. """ if fReadOnly is None or self._fReadOnly: fReadOnly = self._fReadOnly; assert len(aoSchedGroupBoxes) <= len(aoAllRelevantTestBoxes); self._addLabel(sName, sLabel); if not aoAllRelevantTestBoxes: return self._add(u'
  • No test boxes.
  • \n') self._add(u'\n' % ( SchedGroupDataEx.ksParam_aidTestBoxes, ','.join([unicode(oTestBox.idTestBox) for oTestBox in aoAllRelevantTestBoxes]), )); sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else ''; oDefMember = TestBoxDataForSchedGroup(); aoSchedGroupBoxes = list(aoSchedGroupBoxes); # Copy it so we can pop. from testmanager.webui.wuiadmintestbox import WuiTestBoxDetailsLink; if not fUseTable: # # Non-table version (see also addListOfOsArches). # self._add('
    \n'); for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes): # Is it a member? oMember = None; for i, _ in enumerate(aoSchedGroupBoxes): if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox: oMember = aoSchedGroupBoxes.pop(i); break; # Start on the rows... sPrf = u'%s[%d]' % (sName, oTestBox.idTestBox,); self._add(u'
    \n' u' \n' # idTestBox u' \n' # idSchedGroup u' \n' # tsExpire u' \n' # tsEffective u' \n' # uidAuthor u' \n' #(list) % ( iTestBox & 7, sPrf, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox, sPrf, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup, sPrf, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire, sPrf, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective, sPrf, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor, SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr, oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName), )); self._add(u' ' u'\n' % ( sPrf, TestBoxDataForSchedGroup.ksParam_iSchedPriority, (oMember if oMember is not None else oDefMember).iSchedPriority, ' readonly class="tmform-input-readonly"' if fReadOnly else '', escapeAttr("Priority [0..31]. Higher value means run more often.") )); self._add(u' %s\n' % ( WuiTestBoxDetailsLink(oTestBox, sName = '%s (%s)' % (oTestBox.sName, oTestBox.sOs,)),)); self._add(u'
    \n'); return self._add(u'
    \n' u' \n'); # # Table version. # self._add(u'\n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' ); for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes): # Is it a member? oMember = None; for i, _ in enumerate(aoSchedGroupBoxes): if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox: oMember = aoSchedGroupBoxes.pop(i); break; # Start on the rows... sPrefix = u'%s[%d]' % (sName, oTestBox.idTestBox,); self._add(u' \n' u' \n' % ( 'tmodd' if iTestBox & 1 else 'tmeven', sPrefix, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox, sPrefix, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup, sPrefix, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire, sPrefix, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective, sPrefix, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor, SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr, oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName), )); self._add(u' \n' % ( escapeElem(oTestBox.sName), )); self._add(u' \n' % ( sPrefix, TestBoxDataForSchedGroup.ksParam_iSchedPriority, (oMember if oMember is not None else oDefMember).iSchedPriority, ' readonly class="tmform-input-readonly"' if fReadOnly else '', )); self._add(u' \n'); return self._add(u' \n' u'
    Test BoxPriority [0..31]
    \n' u' \n' # idTestBox u' \n' # idSchedGroup u' \n' # tsExpire u' \n' # tsEffective u' \n' # uidAuthor u' \n' #(list) u' %s\n' u' \n' u'
    \n'); def addListOfSchedGroupsForTestBox(self, sName, aoInSchedGroups, aoAllSchedGroups, sLabel, # pylint: disable=too-many-locals idTestBox, fReadOnly = None): # type: (str, TestBoxInSchedGroupDataEx, SchedGroupData, str, bool) -> str """ For WuiTestGroup. """ from testmanager.core.testbox import TestBoxInSchedGroupData, TestBoxDataEx; if fReadOnly is None or self._fReadOnly: fReadOnly = self._fReadOnly; assert len(aoInSchedGroups) <= len(aoAllSchedGroups); # Only show selected groups in read-only mode. if fReadOnly: aoAllSchedGroups = [oCur.oSchedGroup for oCur in aoInSchedGroups] self._addLabel(sName, sLabel); if not aoAllSchedGroups: return self._add('
  • No scheduling groups.
  • \n') # Add special parameter with all the scheduling group IDs in the form. self._add(u'\n' % ( TestBoxDataEx.ksParam_aidSchedGroups, ','.join([unicode(oSchedGroup.idSchedGroup) for oSchedGroup in aoAllSchedGroups]), )); # Table header. self._add(u'\n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' u' \n' ); # Table body. if self._fReadOnly: fReadOnly = True; sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else ''; oDefMember = TestBoxInSchedGroupData(); aoInSchedGroups = list(aoInSchedGroups); # Copy it so we can pop. for iSchedGroup, oSchedGroup in enumerate(aoAllSchedGroups): # Is it a member? oMember = None; for i, _ in enumerate(aoInSchedGroups): if aoInSchedGroups[i].idSchedGroup == oSchedGroup.idSchedGroup: oMember = aoInSchedGroups.pop(i); break; # Start on the rows... sPrefix = u'%s[%d]' % (sName, oSchedGroup.idSchedGroup,); self._add(u' \n' u' \n' % ( 'tmodd' if iSchedGroup & 1 else 'tmeven', sPrefix, TestBoxInSchedGroupData.ksParam_idSchedGroup, oSchedGroup.idSchedGroup, sPrefix, TestBoxInSchedGroupData.ksParam_idTestBox, idTestBox, sPrefix, TestBoxInSchedGroupData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire, sPrefix, TestBoxInSchedGroupData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective, sPrefix, TestBoxInSchedGroupData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor, TestBoxDataEx.ksParam_aoInSchedGroups, '' if oMember is None else ' checked', sCheckBoxAttr, oSchedGroup.idSchedGroup, oSchedGroup.idSchedGroup, escapeElem(oSchedGroup.sName), )); self._add(u' \n' % ( escapeElem(oSchedGroup.sName), )); self._add(u' \n' % ( sPrefix, TestBoxInSchedGroupData.ksParam_iSchedPriority, (oMember if oMember is not None else oDefMember).iSchedPriority, ' readonly class="tmform-input-readonly"' if fReadOnly else '', )); self._add(u' \n'); return self._add(u' \n' u'
    Schedulding GroupPriority [0..31]
    \n' u' \n' # idSchedGroup u' \n' # idTestBox u' \n' # tsExpire u' \n' # tsEffective u' \n' # uidAuthor u' \n' #(list) u' %s\n' u' \n' u'
    \n'); # # Buttons. # def addSubmit(self, sLabel = 'Submit'): """Adds the submit button to the form.""" if self._fReadOnly: return True; return self._add(u'
  • \n' u'
    \n' u'
    \n' u' \n' u' \n' u'
    \n' u'
  • \n' % (escapeElem(sLabel),)); def addReset(self): """Adds a reset button to the form.""" if self._fReadOnly: return True; return self._add(u'
  • \n' u'
    \n' u' \n' u'
    \n' u'
  • \n');