[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r7882 - trunk/gnue-common/src/formatting/masks
From: |
jamest |
Subject: |
[gnue] r7882 - trunk/gnue-common/src/formatting/masks |
Date: |
Fri, 26 Aug 2005 22:50:59 -0500 (CDT) |
Author: jamest
Date: 2005-08-26 22:50:57 -0500 (Fri, 26 Aug 2005)
New Revision: 7882
Modified:
trunk/gnue-common/src/formatting/masks/InputMask.py
trunk/gnue-common/src/formatting/masks/MaskParser.py
Log:
docstrings and cleanup
Modified: trunk/gnue-common/src/formatting/masks/InputMask.py
===================================================================
--- trunk/gnue-common/src/formatting/masks/InputMask.py 2005-08-25 16:38:04 UTC
(rev 7881)
+++ trunk/gnue-common/src/formatting/masks/InputMask.py 2005-08-27 03:50:57 UTC
(rev 7882)
@@ -23,7 +23,8 @@
#
# DESCRIPTION:
"""
-Input masks for GNUe Forms, et al
+Input masks for GNUe Forms, et al
+
Based on lex/yacc parsing (via Plex)
"""
# NOTES:
@@ -151,6 +152,11 @@
first_state = mstate
except Errors.PlexError, msg:
+ import sys
+ mesg = u_("input error:\n%(exType)s\n%(exMessage)s") \
+ % {'exType' : sys.exc_info ()[0],
+ 'exMessage': sys.exc_info ()[1]}
+ print mesg
raise InvalidInputCharacter, msg
@@ -309,10 +315,28 @@
# ===========================================================================
def __init__(self, mask, numeric=False, date=False):
+ """
+ InputMask constructor
+
+ InputMasks can be of 3 differnt types (text, numeric, and date). The type
of
+ input mask is determined by the boolean values of the numeric and date
+ arguments to the constructor. The default mask type is text but if either
+ of the two booleans are set then the mask type switchs to that.
+
+ When building an input mask 2 token lists are built. The initial token
list
+ is created from the mask text passed into the constructor. This token list
+
+ @param mask: The input mask the initialized instance of the class should
+ support
+ @param numeric: Is this input mask numeric input only?
+ @param date: Is this input mask date input only?
+ """
# -------------------------------------------------------------------------
# Generate a list of parser tokens that define the input mask
# -------------------------------------------------------------------------
+ #
parser = MaskParser.InputMaskParser(StringIO(mask),'inline', numeric, date)
+
self.pp = pprint.PrettyPrinter(indent=4)
self.isnumeric = numeric
self.isdate = date
@@ -321,10 +345,10 @@
# List of all tokens. Note that all {#}
# expansions have already happened.
ptokens = parser.tokens
- print "1st token list"
- for item in ptokens:
- print item.token,
- print
+# print "1st token list"
+# for item in ptokens:
+# print item.token,
+# print
# If non-zero, position of the right-to-left token
rtl_pos = self.rtl_pos = parser.rtl_pos
@@ -342,6 +366,8 @@
# -------------------------------------------------------------------------
# Convert the parser token list into an input mask token list
# -------------------------------------------------------------------------
+ #
+ #
i = 0
while i < len(ptokens):
ptoken=ptokens[i]
Modified: trunk/gnue-common/src/formatting/masks/MaskParser.py
===================================================================
--- trunk/gnue-common/src/formatting/masks/MaskParser.py 2005-08-25
16:38:04 UTC (rev 7881)
+++ trunk/gnue-common/src/formatting/masks/MaskParser.py 2005-08-27
03:50:57 UTC (rev 7882)
@@ -33,12 +33,14 @@
import string
from Errors import *
+# TODO: Why is this here?
digit = Any(string.digits)
class BaseToken:
"""
- Basic parser class. Not used directly,
- but inherited by the other defined tokens
+ Basic parser token class.
+
+ Not used directly, but inherited by the other defined tokens
Literal, Token, etc.
"""
numeric=False
@@ -48,6 +50,9 @@
token=False
def __init__(self, t1, t2=None, *args):
+ """
+ Token construtor
+ """
if t2:
self.token = t2
else:
@@ -83,6 +88,8 @@
class TextToken(Token):
"""
Text token
+
+ A test token represents 1 standard alphanumeric character.
"""
text = True
@@ -95,11 +102,9 @@
def __init__(self, token, *args):
# TODO: Expand the set
# Are we all-numeric?
- self.numeric = True
+ self.numeric = token.isdigit()
self.token = token
- for t in token:
- if not t in string.digits:
- self.numeric = False
+
if not self.numeric:
self.text = True
@@ -154,9 +159,14 @@
# =============================================================================
class InputMaskParser(Scanner):
"""
+ Custom plex scanner used to contstruct the TODO: put name here
+ from an input mask passed in during initialization.
+
Takes a file handle containing an input mask and creates a
- list of Tokens which define the input mask.
+ list of Tokens which define the input mask
"""
+
+
def getType(self):
"""
Returns the apparent type of this mask.
@@ -222,93 +232,231 @@
self.produce(Literal(text))
def _repeater(self, text):
+ """
+ Action to process an input mask repeater.
+
+ A repeater tells the parser to repeat the previous token a
+ specified number of times.
+
+ @param text: The value pulled from between the {} which
+ denotes the number of times to repeat.
+ """
self.produce(Repeater(int(text)))
def _begin_set(self, text):
+ """
+ Action to process the start of a set of valid characters.
+
+ The scanner will be placed into set state and the list
+ of valid characters will be reset.
+ """
self.begin('set')
self._set = ""
def _add_set(self, text):
+ """
+ Action to add a character to the set currently being constructed.
+
+ Only called when the scanner is in state "set".
+
+ The character read will be added to the character sting
+ containing the possible valid values.
+ """
self._set += text
def _add_set_2nd(self, text):
+ """
+ Action to add a special character to a set being built.
+
+ Used when an escaped set character \[ or \] is found
+ in the list of valid characters to be added to the set
+ """
return self.add_set(text[1:])
def _end_set(self, text):
+ """
+ Action to process the end of a set.
+
+ Only called when the scanner is in state "set".
+
+ The list of possible characters that were defined in the set will be used
+ to build an instance of a TokenSet class. As part of this function the
+ scanner will set to default state.
+ """
self.begin('')
self.produce(TokenSet(self._set))
- # Basic lexicon used by both input and output masks
+ # ===========================================================================
+ # Lexicon defintions
+ # ===========================================================================
+ #
+ # ---------------------------------------------------------------------------
+ # Base Lexicon definition
+ # ---------------------------------------------------------------------------
+ # This lexicon is the base used by all masks
+ #
_lexicon = [
+ # -----------------------------------------------------------------------
+ # Default state definitions
+ # -----------------------------------------------------------------------
+ (Str('\\'), Begin('escape')), # found \, set state to escape
+ #
+ (Str("'"), Begin('quoted')), # found ', set state to quoted
+ #
+ (Str('"'), Begin('quoted2')), # found ", set state to qoute2
+ #
+ (Str('{'), Begin('repeater')), # found {, set state to repeater
+ #
+ (Str('['), _begin_set), # found [, execute _begin_set
+ # the function will set state
+ # to set when executed
+ #
+ (Str(' '), Literal), # found a space
+ # reutrn a literal char instance
+ #
+ (Any('+.,'), _check_single), # these characters can appear
+ # only once in an input mask
+ #
+ (Any('_?AaLlCc'), TextToken), # found a text character
+ # return a text token instance
+ #
+ (Any('MDYyHISPp:/'), DateToken), # found a date character
+ # return a date token instance
+ #
+ (Any('#0'), NumberToken), # found a number character
+ # return a number token instance
+ #
+ (Any('<>'), CaseModifier), # found a case modifier
+ # return case modifier instance
+
+ # -----------------------------------------------------------------------
+ # Escape State
+ # -----------------------------------------------------------------------
+ # The escape state is entered whenever a backslash is encountered while
+ # in the default state. It's purpose is to allow the placement of what
+ # would normally be reserved characters into the input mask
+ #
State('escape', [
- (AnyChar, _escape),
+ (AnyChar, _escape), # No matter which character is next
+ # execute _escape, the function will
+ # create a literal instance and set
+ # the state back to default
]),
+ # -----------------------------------------------------------------------
+ # Quoted state
+ # -----------------------------------------------------------------------
+ # The quoted state is entered whenevre a single quote is encountered
+ # thile in the default state. It's purpose is to allow quoted strings
+ # inside the input mask to sent through as their literal value
+ #
State('quoted', [
- (Str("\\")+Str("'"), _literal_2nd),
- (Str("'"), Begin('')),
- (AnyChar, _literal)
+ (Str("\\")+Str("'"), _literal_2nd), # Handle \' in the string
+ (Str("'"), Begin('')), # found ', set state to default
+ (AnyChar, _literal) # Process as literal character
]),
+ # -----------------------------------------------------------------------
+ # quote2 state
+ # -----------------------------------------------------------------------
+ # This works the exact same way as the quoted state but is used
+ # when a double quote is encountered. ' and " get seperate states
+ # so that one type can always enclose the other
+ #
+ # Example : "Today's date: "
+ #
State('quoted2', [
- (Str("\\")+Str('"'), _literal_2nd),
- (Str('"'), Begin('')),
- (AnyChar, _literal)
+ (Str("\\")+Str('"'), _literal_2nd), # Handle \" in the string
+ (Str('"'), Begin('')), # found ", set state to default
+ (AnyChar, _literal) # Process as literal character
]),
+ # -----------------------------------------------------------------------
+ # repeater state
+ # -----------------------------------------------------------------------
+ # The repeater state is entered whenever a { is encountered
+ # while in the default state. This state allows an input
+ # mask to include a number inside of {} to cause the previous
+ # token to repeat
+ #
+ # Example : A{5} is the same as AAAAA
+ #
State('repeater', [
- (Str('}'), Begin('')),
- (Rep1(digit), _repeater)
+ (Str('}'), Begin('')), # found }, set state to default
+ (Rep1(digit), _repeater) # grab all digits inside the {}
+ # execute _repeater, the function
+ # will recreate a repeater instance
+ # containing the obtained number
]),
+ # -----------------------------------------------------------------------
+ # Set state
+ # -----------------------------------------------------------------------
+ # The set state is entered whenever a [ is encountered while in the
+ # default state. This provides basic regex set support where any
+ # character inside the [] is matched.
+ #
+ # Example : [ABCDEF]
+ #
State('set', [
- (Str("\\")+Any('[]'), _add_set_2nd),
- (Str(']'), _end_set),
- (AnyChar, _add_set)
+ (Str("\\")+Any('[]'), _add_set_2nd), #
+ (Str(']'), _end_set), #
+ (AnyChar, _add_set) #
]),
-
- (Str('\\'), Begin('escape')),
- (Str("'"), Begin('quoted')),
- (Str('"'), Begin('quoted2')),
- (Str('{'), Begin('repeater')),
- (Str('['), _begin_set),
- (Str(' '), Literal),
- (Any('+.,'), _check_single),
- (Any('_?AaLlCc'), TextToken),
- (Any('MDYyHISPp:/'), DateToken),
- (Any('#0'), NumberToken),
- (Any('<>'), CaseModifier)
]
- # Lexicon used by input masks
+ # ---------------------------------------------------------------------------
+ # Additional lexicon definitions for input masks
+ # ---------------------------------------------------------------------------
_extra_lexicon = [
(Any('!'), _check_single),
]
def __process(self, token):
"""
- Adds the standard tokens to the list of tokens
- generated for this input mask. Deals with special
- tokens.
+ Adds a token class instance to this instances list of tokens.
+
+ As token instances are generated from the input mask they
+ are processed and then added to the scanners working list
+ of tokens. Special tokens such as repeater and case modifiers
+ are processed during this state.
"""
+
if isinstance(token,Repeater):
+ # If the incoming token is a repeater then replace
+ # the repeater with the appropriate number of the
+ # previous token.
for i in range(0, token.count-1):
self.__process(self.__last)
elif isinstance(token, CaseModifier):
+ # If then incomming token is a case modifier
+ # then add the modifier token to the list of
+ # modifiers stored in the scanner
self.__modify.append(token)
else:
+ # Standard tokens
if self.__modify and isinstance(token, TextToken):
+ # If a case modifier is stored and the incoming
+ # token is text then force case based upon the
+ # modifier
mod = self.__modify.pop(0)
if mod.token == '<':
token.force_upper = True
elif mod.token == '>':
token.force_lower = True
+
self.tokens.append(token)
- self.__last = token
+ # TODO: Should this be storing modifiers and the like? It is.
+ self.__last = token
def __init__(self, file, name, numeric=False, date=False):
"""
+ Input mask scanner constructor.
+
+ The input mask scanner will create a list of class instances
+ that describe the input mask.
+
@type file: input stream
@param file: The text to be used as the mask
@type name: string
@@ -320,8 +468,10 @@
"""
self.__singles = []
self.tokens = []
- self.__last = None
+ self.__last = None # The last token generated from the input mask
self.__modify = []
+
+
# -------------------------------------------------------------------------
# Read the input mask and convert into instances of Token classes
# -------------------------------------------------------------------------
@@ -332,6 +482,8 @@
token, extra = self.read()
if token is None:
break
+
+ # Process the returned token
self.__process(token)
except Errors.PlexError, msg:
@@ -341,20 +493,18 @@
print "WARNING: Modifier found at end of mask."
# -------------------------------------------------------------------------
- # Set appropriate flags
+ # Build a count of the various token types created during parsing
# -------------------------------------------------------------------------
+ #
+ num_markers = 0 # Number of numeric token instances found
+ date_markers = 0 # Number of date token instances found
+ text_markers = 0 # Number of text token instances found
+ rtl_pos = -1 # Right to left token
+ # TODO: Unknown functionality at this time
- # If any two of these are non-zero, then the
- # mask is a text mask, not date or numeric.
- num_markers = 0
- date_markers = 0
- text_markers = 0
- rtl_pos = -1
-
- i = 0
- for token in self.tokens:
+ for (position, token) in enumerate(self.tokens):
if isinstance(token,RightToLeft):
- rtl_pos = i
+ rtl_pos = position
if not isinstance(token, Literal):
if token.numeric:
num_markers += 1
@@ -362,8 +512,18 @@
date_markers += 1
else:
text_markers += 1
- i += 1
+
+ # Check for "!" in non-numeric mask
+ if rtl_pos >= 0:
+ self.tokens.pop(rtl_pos)
+ else:
+ rtl_pos = 0
+ self.rtl_pos = rtl_pos
+
+ # -------------------------------------------------------------------------
+ # Check for errors and mixed marker types
+ # -------------------------------------------------------------------------
if not (num_markers or date_markers or text_markers):
raise MaskDefinitionError, 'Mask has no character tokens'
@@ -373,15 +533,12 @@
if date and (num_markers or text_markers):
raise MaskDefinitionError, 'Date/Time mask has non-date tokens'
- # Check for "!" in non-numeric mask
- if rtl_pos >= 0:
- self.tokens.pop(rtl_pos)
- else:
- rtl_pos = 0
-
- self.rtl_pos = rtl_pos
-
- # Set the type of parser
+ # -------------------------------------------------------------------------
+ # Set the type of parser based upon the marker counts
+ # -------------------------------------------------------------------------
+ # If any two of these are non-zero, then the mask is a text mask,
+ # not date or numeric.
+ #
if (num_markers and date_markers) or text_markers:
self.type = 'text'
elif num_markers:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7882 - trunk/gnue-common/src/formatting/masks,
jamest <=