changeset 3403:d479e393e318

wikiutil.parse_quoted_separated_ext: allow for prefixes
author Johannes Berg <johannes AT sipsolutions DOT net>
date Sat, 22 Mar 2008 03:00:25 +0100
parents 4b94ff6a4073
children e979e3cad972
files MoinMoin/_tests/test_wikiutil.py MoinMoin/wikiutil.py
diffstat 2 files changed, 73 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/_tests/test_wikiutil.py	Sat Mar 22 02:36:45 2008 +0100
+++ b/MoinMoin/_tests/test_wikiutil.py	Sat Mar 22 03:00:25 2008 +0100
@@ -417,6 +417,54 @@
         for test in tests:
             yield [_check] + list(test)
 
+    def testExtendedParserPrefix(self):
+        P = wikiutil.ParserPrefix('+')
+        M = wikiutil.ParserPrefix('-')
+        tests = [
+            (u'"a", "b", "c"', u',', None, [u'a', u'b', u'c']),
+            (u'a:b, b:c, c:d', u',', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
+            (u'a:b, b:c, c:d', u',', None, [u'a:b', u'b:c', u'c:d']),
+            (u'a=b, b=c, c=d', u',', None, [u'a=b', u'b=c', u'c=d']),
+            (u'a=b, b=c, c=d', u',', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
+            (u'"a"; "b"; "c"', u';', None, [u'a', u'b', u'c']),
+            (u'a:b; b:c; c:d', u';', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
+            (u'a:b; b:c; c:d', u';', None, [u'a:b', u'b:c', u'c:d']),
+            (u'a=b; b=c; c=d', u';', None, [u'a=b', u'b=c', u'c=d']),
+            (u'a=b; b=c; c=d', u';', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
+            (u'"a" "b" "c"', None, None, [u'a', u'b', u'c']),
+            (u'" a " "b" "c"', None, None, [u' a ', u'b', u'c']),
+            (u'"a  " "b" "c"', None, None, [u'a  ', u'b', u'c']),
+            (u'"  a" "b" "c"', None, None, [u'  a', u'b', u'c']),
+            (u'"  a" "b" "c"', None, u':', [u'  a', u'b', u'c']),
+            (u'"a:a" "b:b" "c:b"', None, u':', [u'a:a', u'b:b', u'c:b']),
+            (u'   a:a  ', None, u':', [None, None, None, (u'a', u'a'), None, None]),
+            (u'a a: a', None, u':', [u'a', (u'a', None), u'a']),
+            (u'a a:"b c d" a', None, u':', [u'a', (u'a', u'b c d'), u'a']),
+            (u'a a:"b "" d" a', None, u':', [u'a', (u'a', u'b " d'), u'a']),
+            (u'title:Help* dog cat', None, u':', [(u'title', u'Help*'), u'dog', u'cat']),
+            (u'title:Help* "dog cat"', None, u':', [(u'title', u'Help*'), u'dog cat']),
+            (u'a:b:c d:e:f', None, u':', [(u'a', u'b', u'c'), (u'd', 'e', u'f')]),
+            (u'a:b:c:d', None, u':', [(u'a', u'b', u'c', u'd')]),
+            (u'a:"b:c":d', None, u':', [(u'a', u'b:c', u'd')]),
+
+            (u'-a:b:d', None, u':', [(M, u'a', u'b', u'd')]),
+            (u'"-a:b:d"', None, u':', [(u'-a:b:d')]),
+            (u'-"a:b:d"', None, u':', [(M, u'a:b:d')]),
+            (u'-a:"b:c":"d e f g"', None, u':', [(M, u'a', u'b:c', u'd e f g')]),
+            (u'+-a:b:d', None, u':', [(P, u'-a', u'b', u'd')]),
+            (u'-"+a:b:d"', None, u':', [(M, u'+a:b:d')]),
+            # bit of a weird case...
+            (u'-+"a:b:d"', None, u':', [(M, u'+"a', u'b', u'd"')]),
+            (u'-a:"b:c" a +b', None, u':', [(M, u'a', u'b:c'), u'a', (P, u'b')]),
+        ]
+
+        def _check(args, sep, kwsep, expected):
+            res = wikiutil.parse_quoted_separated_ext(args, sep, kwsep, multikey=True, prefixes='-+')
+            assert res == expected
+
+        for test in tests:
+            yield [_check] + list(test)
+
     def testExtendedParserBracketingErrors(self):
         UCE = wikiutil.BracketUnexpectedCloseError
         MCE = wikiutil.BracketMissingCloseError
--- a/MoinMoin/wikiutil.py	Sat Mar 22 02:36:45 2008 +0100
+++ b/MoinMoin/wikiutil.py	Sat Mar 22 03:00:25 2008 +0100
@@ -1265,8 +1265,24 @@
         self.bracket = bracket
         BracketError.__init__(self, "Missing closing bracket %s" % bracket)
 
+class ParserPrefix:
+    """
+    Trivial container-class holding a single character for
+    the possible prefixes for parse_quoted_separated_ext
+    and implementing rich equal comparison.
+    """
+    def __init__(self, prefix):
+        self.prefix = prefix
+
+    def __eq__(self, other):
+        return isinstance(other, ParserPrefix) and other.prefix == self.prefix
+
+    def __repr__(self):
+        return '<ParserPrefix(%s)>' % self.prefix.encode('utf-8')
+
 def parse_quoted_separated_ext(args, separator=None, name_value_separator=None,
-                               brackets=None, seplimit=0, multikey=False):
+                               brackets=None, seplimit=0, multikey=False,
+                               prefixes=None):
     """
     Parses the given string according to the other parameters.
 
@@ -1279,7 +1295,11 @@
     empty string as a value can be achieved by quoting it.
 
     If a name or value does not start with a quote, then the quote
-    looses its special meaning for that name or value.
+    looses its special meaning for that name or value, unless it
+    starts with one of the given prefixes (the parameter is unicode
+    containing all allowed prefixes.) The prefixes will be returned
+    as ParserPrefix() instances in the first element of the tuple
+    for that particular argument.
 
     If multiple separators follow each other, this is treated as
     having None arguments inbetween, that is also true for when
@@ -1440,6 +1460,9 @@
             del bracketstack[-1]
             oldresult.append(result)
             result = oldresult
+        elif not quoted and prefixes and char in prefixes and cur == [None]:
+            cur = [ParserPrefix(char)]
+            cur.append(None)
         else:
             if len(cur):
                 if cur[-1] is None: