From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../ValidationKit/testmanager/webui/wuihlpform.py | 1111 ++++++++++++++++++++ 1 file changed, 1111 insertions(+) create mode 100755 src/VBox/ValidationKit/testmanager/webui/wuihlpform.py (limited to 'src/VBox/ValidationKit/testmanager/webui/wuihlpform.py') diff --git a/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py b/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py new file mode 100755 index 00000000..38015e83 --- /dev/null +++ b/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py @@ -0,0 +1,1111 @@ +# -*- 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'); + -- cgit v1.2.3