[qmtest] FileContentsTest multiple substitutions?
Mark Mitchell
mark at codesourcery.com
Thu Dec 19 07:37:05 UTC 2002
--On Wednesday, December 18, 2002 08:01:20 PM -0500 "eichin at metacarta.com"
<eichin at metacarta.com> wrote:
> This fixes it for me - I'm not sure if it is a good fix (having not
> heard if anyone else has the problem, it may just be due to my not
> understanding DOM) but it at least makes some sense... _Mark_
I checked in this version. Note the NEWS entry; we could make this
backwards-compatible if we need to do so.
Do people have lots of FileContentsTests out there?
--
Mark Mitchell mark at codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
Index: ChangeLog
===================================================================
RCS file: /home/sc/Repository/qm/ChangeLog,v
retrieving revision 1.429.2.5
diff -c -5 -p -r1.429.2.5 ChangeLog
*** ChangeLog 19 Dec 2002 05:50:06 -0000 1.429.2.5
--- ChangeLog 19 Dec 2002 07:36:37 -0000
***************
*** 1,7 ****
--- 1,13 ----
2002-12-18 Mark Mitchell <mark at codesourcery.com>
+ * qm/test/classes/file.py (SubstitutionField): Rework, using
+ TupleField as a base class.
+ (FileContentsTest.Run): Remove exception-handling code.
+ (FileContentsTest.__PerformSubstitutions): Correct.
+ * NEWS: Mention change.
+
* qm/fields.py (ChoiceField): New class.
* qm/test/test.py (Test.ResourceField): Likewise.
(Test.TestField): Likewise.
(Test.arguments): Use them.
Index: NEWS
===================================================================
RCS file: /home/sc/Repository/qm/NEWS,v
retrieving revision 1.11.2.2
diff -c -5 -p -r1.11.2.2 NEWS
*** NEWS 18 Dec 2002 05:29:16 -0000 1.11.2.2
--- NEWS 19 Dec 2002 07:36:37 -0000
*************** QM 2.0.2
*** 9,18 ****
--- 9,25 ----
When a test fails due to dependency on a resource that could not be
set up, the GUI now displays a link to the resource result from the
test result. (Previously, there was no way to get information about
resource failures in the GUI.)
+ The GUI now offers a choice of available prerequisite tests and
+ resources when editing a test.
+
+ The substitutions field for the FileContentsTest now works correctly
+ in the GUI. This is an incompatible change; tests that use this test
+ class will require hand-editing.
+
QM 2.0.1
========
A bug that prevented the "New Resource" entry on the "File" menu from
working has been fixed.
Index: qm/test/classes/file.py
===================================================================
RCS file: /home/sc/Repository/qm/qm/test/classes/file.py,v
retrieving revision 1.13
diff -c -5 -p -r1.13 file.py
*** qm/test/classes/file.py 17 Oct 2002 20:38:15 -0000 1.13
--- qm/test/classes/file.py 19 Dec 2002 07:36:38 -0000
*************** import string
*** 29,39 ****
########################################################################
# classes
########################################################################
! class SubstitutionField(qm.fields.TextField):
"""A rule for performing a text substitution.
A 'SubstitutionField' consists of a regular expression pattern and a
corresponding replacement string. When the substitution is applied
to a body of text, all substrings that match the pattern are
--- 29,39 ----
########################################################################
# classes
########################################################################
! class SubstitutionField(qm.fields.TupleField):
"""A rule for performing a text substitution.
A 'SubstitutionField' consists of a regular expression pattern and a
corresponding replacement string. When the substitution is applied
to a body of text, all substrings that match the pattern are
*************** class SubstitutionField(qm.fields.TextFi
*** 42,153 ****
The syntax for the regular expression and the substitution string is
that of the standard Python 're' (regular expression) module."""
class_name = "qm.test.classes.file.SubstitutionField"
- # The pattern and replacement string are encoded together into a
- # single string, separated by a semicolon. Semicolons that occur
- # within the pattern and replacement string are escaped with a
- # backslash.
- #
- # Use 'SplitValue' to extract the pattern and replacement string
- # from a value of this field.
-
-
def __init__(self, name, **properties):
"""Create a new 'SubstitutionField'.
By default, the pattern and replacement string are empty."""
# Initialize the base class.
! qm.fields.TextField.__init__(self, name, ";", **properties)
!
!
! def SplitValue(self, value):
! """Split a value of this field into the pattern and replacement
string.
!
! 'value' -- A value for this field.
!
! returns -- A pair '(pattern, replacement_string)'."""
!
! # Be lenient about an empty string.
! if value == "":
! return ("", "")
! # Break it in half.
! elements = string.split(value, ";", 1)
! # Unescape semicolons in both halves.
! elements = map(lambda e: string.replace(e, r"\;", ";"), elements)
! return elements
!
!
! def FormatValueAsHtml(self, value, style, name=None):
! pattern, replacement = self.SplitValue(value)
! # Since we're generating HTML, escape special characters.
! pattern = qm.web.escape(pattern)
! replacement = qm.web.escape(replacement)
!
! if style in ["new", "edit"]:
! result = '''
! <input type="hidden"
! name="%(name)s"
! value="%(value)s"/>
! <table border="0" cellpadding="0" cellspacing="4">
! <tr>
! <td>Pattern:</td>
! <td> </td>
! <td><input type="text"
! size="40"
! name="pattern"
! onchange="update_substitution();"
! value="%(pattern)s"/></td>
! </tr>
! <tr>
! <td>Replacement:</td>
! <td> </td>
! <td><input type="text"
! size="40"
! name="substitution"
! onchange="update_substitution();"
! value="%(replacement)s"/></td>
! </tr>
! </table>
! <script language="JavaScript">
! function update_substitution()
! {
! var pattern = document.form.pattern.value;
! pattern = pattern.replace(/;/g, "\\;");
! var substitution = document.form.substitution.value;
! substitution = substitution.replace(/;/g, "\\;");
! document.form.%(name)s.value = pattern + ";" + substitution;
! }
! </script>
! ''' % locals()
! return result
!
! elif style == "full":
! return '''
! <table border="0" cellpadding="2" cellspacing="0">
! <tr valign="top">
! <td>Pattern:</td>
! <td><tt>%s</tt></td>
! </tr>
! <tr valign="top">
! <td>Replacement:</td>
! <td><tt>%s</tt></td>
! </tr>
! </table>
! ''' % (pattern, replacement)
!
! else:
! # For all other styles, use the base class implementation.
! return qm.fields.TextField.FormatValueAsHtml(
! self, value, style, name)
!
!
! def FormatValueAsText(self, value, columns=72):
! # Don't line-wrap or otherwise futz with the value.
! return value
def GetHelp(self):
return """
A substitution consists of a regular expression pattern and a
--- 42,62 ----
The syntax for the regular expression and the substitution string is
that of the standard Python 're' (regular expression) module."""
class_name = "qm.test.classes.file.SubstitutionField"
def __init__(self, name, **properties):
"""Create a new 'SubstitutionField'.
By default, the pattern and replacement string are empty."""
# Initialize the base class.
! fields = (qm.fields.TextField(name = "pattern",
! title = "Pattern",),
! qm.fields.TextField(name = "replacement",
! title = "Replacement"))
! qm.fields.TupleField.__init__(self, name, fields, **properties)
def GetHelp(self):
return """
A substitution consists of a regular expression pattern and a
*************** class SubstitutionField(qm.fields.TextFi
*** 155,167 ****
subtrings matching the pattern are replaced with the
substitution string. The substitution string may reference
matched groups in the pattern.
The regular expression and substitution syntax are those of
! Python's standard "'re' regular expression module"
!
! .. "'re' regular expression module"
http://www.python.org/doc/1.5.2p2/lib/module-re.html ."""
class FileContentsTest(Test):
"""Check that the contents of a file match the expected value.
--- 64,74 ----
subtrings matching the pattern are replaced with the
substitution string. The substitution string may reference
matched groups in the pattern.
The regular expression and substitution syntax are those of
! Python's standard "'re' regular expression module"."""
class FileContentsTest(Test):
"""Check that the contents of a file match the expected value.
*************** class FileContentsTest(Test):
*** 213,237 ****
]
def Run(self, context, result):
# Extract the path to the file we're testing.
! try:
! path = context[self.path_property]
! except KeyError:
! # The path is not present in the context under the expected
! # property name.
! result.Fail("Missing property '%s' in context." %
! self.path_property)
# Read the contents of the file.
! try:
! contents = open(path, "r").read()
! except IOError, exception:
! # Couldn't read the file.
! result.Fail(cause="Could not open file '%s'." % path,
! annotations={ "FileContentsTest.error"
! : str(exception) })
# Perform substitutions on the file contents.
self.expected_contents = \
self.__PerformSubstitutions(self.expected_contents)
contents = self.__PerformSubstitutions(contents)
# Compare the contents to the expected contents.
--- 120,132 ----
]
def Run(self, context, result):
# Extract the path to the file we're testing.
! path = context[self.path_property]
# Read the contents of the file.
! contents = open(path, "r").read()
# Perform substitutions on the file contents.
self.expected_contents = \
self.__PerformSubstitutions(self.expected_contents)
contents = self.__PerformSubstitutions(contents)
# Compare the contents to the expected contents.
*************** class FileContentsTest(Test):
*** 246,258 ****
"""Perform substitutions on a body of text.
returns -- The string 'text', processed with the substitutions
configured for this test instance."""
! substitutions_field = self.arguments[2].GetContainedField()
! for substitution in self.substitutions:
! pattern, replacement =
substitutions_field.SplitValue(substitution)
text = re.sub(pattern, replacement, text)
return text
--- 141,151 ----
"""Perform substitutions on a body of text.
returns -- The string 'text', processed with the substitutions
configured for this test instance."""
! for pattern, replacement in self.substitutions:
text = re.sub(pattern, replacement, text)
return text
More information about the qmtest
mailing list