PATCH: Provide a textual representation for SetField
Mark Mitchell
mark at codesourcery.com
Mon Sep 8 06:51:47 UTC 2003
This patch implements ParseTextValue for SetField so that values can
be specified on the command line.
--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery.com
2003-09-07 Mark Mitchell <mark at codesourcery.com>
* qm/fields.py (cStringIO): Do not import.
(StringIO): Import.
(tokenize): Import.
(Field.FormatValueAsText): Use StringIO.
(Field.ParseTextValue): Improve documentation.
(SetField.FormatValueAsText): Make output match format expected
by ...
(SetField.ParseTextField): ... this new method.
* qm/test/cmdline.py (QMTest.attribute_option_spec): Generalize
help text.
* share/diagnostics/common.txt (invalid set value): New message.
Index: qm/fields.py
===================================================================
RCS file: /home/sc/Repository/qm/qm/fields.py,v
retrieving revision 1.77
diff -c -5 -p -r1.77 fields.py
*** qm/fields.py 30 Jul 2003 21:25:30 -0000 1.77
--- qm/fields.py 8 Sep 2003 06:45:22 -0000
*************** of test names."""
*** 40,59 ****
# imports
########################################################################
import attachment
import common
- import cStringIO
import formatter
import htmllib
import os
import re
import qm
import string
import structured_text
import sys
import time
import types
import urllib
import web
import xml.dom
import xmlutil
--- 40,60 ----
# imports
########################################################################
import attachment
import common
import formatter
import htmllib
import os
import re
import qm
import string
+ import StringIO
import structured_text
import sys
import time
+ import tokenize
import types
import urllib
import web
import xml.dom
import xmlutil
*************** class Field(object):
*** 225,239 ****
'columns' -- The maximum width of each line of text.
returns -- A plain-text string representing 'value'."""
# Create a file to hold the result.
! text_file = cStringIO.StringIO()
# Format the field as HTML.
! html_file = cStringIO.StringIO(self.FormatValueAsHtml(None,
! value,
! "brief"))
# Turn the HTML into plain text.
parser = htmllib.HTMLParser(formatter.AbstractFormatter
(formatter.DumbWriter(text_file,
maxcol = columns)))
--- 226,240 ----
'columns' -- The maximum width of each line of text.
returns -- A plain-text string representing 'value'."""
# Create a file to hold the result.
! text_file = StringIO.StringIO()
# Format the field as HTML.
! html_file = StringIO.StringIO(self.FormatValueAsHtml(None,
! value,
! "brief"))
# Turn the HTML into plain text.
parser = htmllib.HTMLParser(formatter.AbstractFormatter
(formatter.DumbWriter(text_file,
maxcol = columns)))
*************** class Field(object):
*** 307,317 ****
def ParseTextValue(self, value):
"""Parse a value represented as a string.
'value' -- A string representing the value.
! returns -- The corresponding field value."""
raise NotImplemented
def ParseFormValue(self, request, name, attachment_store):
--- 308,320 ----
def ParseTextValue(self, value):
"""Parse a value represented as a string.
'value' -- A string representing the value.
! returns -- The corresponding field value. The value returned
! should be processed by 'Validate' to ensure that it is valid
! before it is returned."""
raise NotImplemented
def ParseFormValue(self, request, name, attachment_store):
*************** class SetField(Field):
*** 868,879 ****
# comma-separated list.
contained_field = self.GetContainedField()
formatted_items = []
for item in value:
formatted_item = contained_field.FormatValueAsText(item, columns)
! formatted_items.append(formatted_item)
! result = string.join(formatted_items, ", ")
return qm.common.wrap_lines(result, columns)
def FormatValueAsHtml(self, server, value, style, name=None):
# Use default value if requested.
--- 871,882 ----
# comma-separated list.
contained_field = self.GetContainedField()
formatted_items = []
for item in value:
formatted_item = contained_field.FormatValueAsText(item, columns)
! formatted_items.append(repr(formatted_item))
! result = "[ " + string.join(formatted_items, ", ") + " ]"
return qm.common.wrap_lines(result, columns)
def FormatValueAsHtml(self, server, value, style, name=None):
# Use default value if requested.
*************** class SetField(Field):
*** 979,988 ****
--- 982,1044 ----
# validating each element in the contained field.
return map(lambda v: self.__contained.Validate(v),
value)
+ def ParseTextValue(self, value):
+
+ def invalid(tok):
+ """Raise an exception indicating a problem with 'value'.
+
+ 'tok' -- A token indicating the position of the problem.
+
+ This function does not return; instead, it raises an
+ appropriate exception."""
+
+ raise qm.QMException, \
+ qm.error("invalid set value", start = value[tok[2][1]:])
+
+ # Use the Python parser to handle the elements of the set.
+ s = StringIO.StringIO(value)
+ g = tokenize.generate_tokens(s.readline)
+
+ # Read the opening square bracket.
+ tok = g.next()
+ if tok[0] != tokenize.OP or tok[1] != "[":
+ invalid(tok)
+
+ # There are no elements yet.
+ elements = []
+
+ # Keep going until we find the closing bracket.
+ while 1:
+ # If we've reached the closing bracket, the set is
+ # complete.
+ tok = g.next()
+ if tok[0] == tokenize.OP and tok[1] == "]":
+ break
+ # If this is not the first element of the set, there should
+ # be a comma before the next element.
+ if elements:
+ if tok[0] != tokenize.OP or tok[1] != ",":
+ invalid(tok)
+ tok = g.next()
+ # The next token should be a string constant.
+ if tok[0] != tokenize.STRING:
+ invalid(tok)
+ # Parse the string constant.
+ v = eval(tok[1])
+ elements.append(self.GetContainedField().ParseTextValue(v))
+
+ # There should not be any tokens left over.
+ tok = g.next()
+ if not tokenize.ISEOF(tok[0]):
+ invalid(tok)
+
+ return self.Validate(elements)
+
+
def ParseFormValue(self, request, name, attachment_store):
values = []
contained_field = self.GetContainedField()
Index: qm/test/cmdline.py
===================================================================
RCS file: /home/sc/Repository/qm/qm/test/cmdline.py,v
retrieving revision 1.95
diff -c -5 -p -r1.95 cmdline.py
*** qm/test/cmdline.py 20 Aug 2003 19:43:28 -0000 1.95
--- qm/test/cmdline.py 8 Sep 2003 06:45:23 -0000
*************** class QMTest:
*** 274,284 ****
attribute_option_spec = (
"a",
"attribute",
"KEY=VALUE",
! "Set a database attribute."
)
extension_kind_option_spec = (
"k",
"kind",
--- 274,284 ----
attribute_option_spec = (
"a",
"attribute",
"KEY=VALUE",
! "Set an attribute of the extension class."
)
extension_kind_option_spec = (
"k",
"kind",
Index: share/diagnostics/common.txt
===================================================================
RCS file: /home/sc/Repository/qm/share/diagnostics/common.txt,v
retrieving revision 1.21
diff -c -5 -p -r1.21 common.txt
*** share/diagnostics/common.txt 14 Apr 2003 06:06:40 -0000 1.21
--- share/diagnostics/common.txt 8 Sep 2003 06:45:23 -0000
*************** The user name or password you entered is
*** 79,88 ****
--- 79,94 ----
@ invalid property
The property '%(error)s' is invalid. Use the form 'NAME=VALUE' to
specify properties.
+ @ invalid set value
+ The set value provided could not be parsed. The invalid part of the
+ value is "%(start)s".
+
+ A valid set value has the form "[ 'value1', 'value2', ... ]".
+
@ missing command
Specify a command.
@ sendmail error
Could not execute your mail transport agent, `%(sendmail_path)s'.
More information about the qmtest
mailing list