[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