changeset 676:cddc53aaa7b8

Merge.
author Alexander Schremmer <alex AT alexanderweb DOT de>
date Sun, 21 May 2006 12:44:52 +0200
parents 6248f0fbc583 (current diff) 84dc5d29721a (diff)
children 421b68c6533b 6ff5221f7e18
files MoinMoin/script/_util.py MoinMoin/util/parameterparser.py MoinMoin/util/wikiext.py MoinMoin/webapi/__init__.py
diffstat 22 files changed, 518 insertions(+), 427 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/script/__init__.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/__init__.py	Sun May 21 12:44:52 2006 +0200
@@ -2,7 +2,8 @@
 """
     MoinMoin - Extension Script Package
 
-    @copyright: 2006 by Thomas Waldmann
+    @copyright: 2000-2002 by Jürgen Hermann <jh@web.de>,
+                2006 by MoinMoin:ThomasWaldmann
     @license: GNU GPL, see COPYING for details.
 """
 
@@ -12,3 +13,137 @@
 extension_scripts = pysupport.getPackageModules(__file__)
 modules = extension_scripts
 
+import os, sys, time
+
+flag_quiet = 0
+script_module = '__main__'
+
+#############################################################################
+### Logging
+#############################################################################
+
+def fatal(msgtext, **kw):
+    """ Print error msg to stderr and exit. """
+    sys.stderr.write("FATAL ERROR: " + msgtext + "\n")
+    if kw.get('usage', 0):
+        maindict = vars(sys.modules[script_module])
+        if maindict.has_key('usage'):
+            maindict['usage']()
+    sys.exit(1)
+
+
+def log(msgtext):
+    """ Optionally print error msg to stderr. """
+    if not flag_quiet:
+        sys.stderr.write(msgtext + "\n")
+
+
+#############################################################################
+### Commandline Support
+#############################################################################
+
+class Script:
+    def __init__(self, script, usage, argv=None, def_values=None):
+        #print "argv:", argv, "def_values:", repr(def_values)
+        if argv is None:
+            self.argv = sys.argv[1:]
+        else:
+            self.argv = argv
+        self.def_values = def_values
+        self.script_module = sys.modules[script]
+
+        global _start_time
+        _start_time = time.clock()
+
+        import optparse
+        from MoinMoin import version
+
+        cmd = self.script_module.__name__.split('.')[-1].replace('_', '-')
+        rev = "%s %s [%s]" % (version.project, version.release, version.revision)
+        sys.argv[0] = cmd
+
+        self.parser = optparse.OptionParser(
+            usage="%(cmd)s %(usage)s\n\n" % {'cmd': cmd, 'usage': usage, },
+            version=rev)
+        self.parser.allow_interspersed_args = False
+        if def_values:
+            self.parser.set_defaults(**def_values.__dict__)
+        self.parser.add_option(
+            "-q", "--quiet", 
+            action="store_true", dest="quiet",
+            help="Be quiet (no informational messages)"
+        )
+        self.parser.add_option(
+            "--show-timing", 
+            action="store_true", dest="show_timing", default=False,
+            help="Show timing values [default: %default]"
+        )
+
+    def run(self, showtime=1):
+        """ Run the main function of a command. """
+        global flag_quiet
+        try:
+            try:
+                self.options, self.args = self.parser.parse_args(self.argv)
+                flag_quiet = self.options.quiet
+                self.mainloop()
+            except KeyboardInterrupt:
+                log("*** Interrupted by user!")
+            except SystemExit:
+                showtime = 0
+                raise
+        finally:
+            if showtime:
+                self.logRuntime()
+
+    def logRuntime(self):
+        """ Print the total command run time. """
+        if self.options.show_timing:
+            log("Needed %.3f secs." % (time.clock() - _start_time,))
+
+
+class MoinScript(Script):
+    """ Moin main script class """
+
+    def __init__(self, argv=None, def_values=None):
+        Script.__init__(self, __name__, "[options]", argv, def_values)
+        # those are options potentially useful for all sub-commands:
+        self.parser.add_option(
+            "--config-dir", metavar="DIR", dest="config_dir",
+            help=("Path to the directory containing the wiki "
+                  "configuration files. [default: current directory]")
+        )
+        self.parser.add_option(
+            "--wiki-url", metavar="WIKIURL", dest="wiki_url",
+            help="URL of a single wiki to migrate e.g. localhost/mywiki/ [default: CLI]"
+        )
+        self.parser.add_option(
+            "--page", dest="page", default='',
+            help="wiki page name [default: %default]"
+        )
+    
+    def init_request(self):
+        """ create request """
+        from MoinMoin.request import CLI
+        if self.options.wiki_url:
+            self.request = CLI.Request(self.options.wiki_url, self.options.page)
+        else:
+            self.request = CLI.Request(pagename=self.options.page)
+        
+    def mainloop(self):
+        # Insert config dir or the current directory to the start of the path.
+        config_dir = self.options.config_dir
+        if config_dir and not os.path.isdir(config_dir):
+            fatal("bad path given to --config-dir option")
+        sys.path.insert(0, os.path.abspath(config_dir or os.curdir))
+
+        args = self.args
+        if len(args) < 2:
+            self.parser.error("you must specify a command module and name.")
+            sys.exit(1)
+
+        cmd_module, cmd_name = args[:2]
+        from MoinMoin import wikiutil
+        plugin_class = wikiutil.importBuiltinPlugin('script.%s' % cmd_module, cmd_name, 'PluginScript')
+        plugin_class(args[2:], self.options).run() # all starts again there
+
--- a/MoinMoin/script/_util.py	Sun May 21 12:43:58 2006 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - Command line utilities
-
-    @copyright: 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
-    @license: GNU GPL, see COPYING for details.
-"""
-
-import os, sys, time
-
-flag_quiet = 0
-script_module = '__main__'
-
-#############################################################################
-### Logging
-#############################################################################
-
-def fatal(msgtext, **kw):
-    """ Print error msg to stderr and exit. """
-    sys.stderr.write("FATAL ERROR: " + msgtext + "\n")
-    if kw.get('usage', 0):
-        maindict = vars(sys.modules[script_module])
-        if maindict.has_key('usage'):
-            maindict['usage']()
-    sys.exit(1)
-
-
-def log(msgtext):
-    """ Optionally print error msg to stderr. """
-    if not flag_quiet:
-        sys.stderr.write(msgtext + "\n")
-
-
-#############################################################################
-### Commandline Support
-#############################################################################
-
-class Script:
-    def __init__(self, script, usage, argv=None, def_values=None):
-        #print "argv:", argv, "def_values:", repr(def_values)
-        if argv is None:
-            self.argv = sys.argv[1:]
-        else:
-            self.argv = argv
-        self.def_values = def_values
-        self.script_module = sys.modules[script]
-
-        global _start_time
-        _start_time = time.clock()
-
-        import optparse
-        from MoinMoin import version
-
-        cmd = self.script_module.__name__.split('.')[-1].replace('_', '-')
-        rev = "%s %s [%s]" % (version.project, version.release, version.revision)
-        sys.argv[0] = cmd
-
-        self.parser = optparse.OptionParser(
-            usage="%(cmd)s %(usage)s\n\n" % {'cmd': cmd, 'usage': usage, },
-            version=rev)
-        self.parser.allow_interspersed_args = False
-        if def_values:
-            self.parser.set_defaults(**def_values.__dict__)
-        self.parser.add_option(
-            "-q", "--quiet", 
-            action="store_true", dest="quiet",
-            help="Be quiet (no informational messages)"
-        )
-        self.parser.add_option(
-            "--show-timing", 
-            action="store_true", dest="show_timing", default=False,
-            help="Show timing values [default: %default]"
-        )
-
-    def run(self, showtime=1):
-        """ Run the main function of a command. """
-        global flag_quiet
-        try:
-            try:
-                self.options, self.args = self.parser.parse_args(self.argv)
-                flag_quiet = self.options.quiet
-                self.mainloop()
-            except KeyboardInterrupt:
-                log("*** Interrupted by user!")
-            except SystemExit:
-                showtime = 0
-                raise
-        finally:
-            if showtime:
-                self.logRuntime()
-
-    def logRuntime(self):
-        """ Print the total command run time. """
-        if self.options.show_timing:
-            log("Needed %.3f secs." % (time.clock() - _start_time,))
-
-
-class MoinScript(Script):
-    """ Moin main script class """
-
-    def __init__(self, argv=None, def_values=None):
-        Script.__init__(self, __name__, "[options]", argv, def_values)
-        # those are options potentially useful for all sub-commands:
-        self.parser.add_option(
-            "--config-dir", metavar="DIR", dest="config_dir",
-            help=("Path to the directory containing the wiki "
-                  "configuration files. [default: current directory]")
-        )
-        self.parser.add_option(
-            "--wiki-url", metavar="WIKIURL", dest="wiki_url",
-            help="URL of a single wiki to migrate e.g. localhost/mywiki/ [default: CLI]"
-        )
-        self.parser.add_option(
-            "--page", dest="page", default='',
-            help="wiki page name [default: %default]"
-        )
-    
-    def init_request(self):
-        """ create request """
-        from MoinMoin.request import CLI
-        if self.options.wiki_url:
-            self.request = CLI.Request(self.options.wiki_url, self.options.page)
-        else:
-            self.request = CLI.Request(pagename=self.options.page)
-        
-    def mainloop(self):
-        # Insert config dir or the current directory to the start of the path.
-        config_dir = self.options.config_dir
-        if config_dir and not os.path.isdir(config_dir):
-            fatal("bad path given to --config-dir option")
-        sys.path.insert(0, os.path.abspath(config_dir or os.curdir))
-
-        args = self.args
-        if len(args) < 2:
-            self.parser.error("you must specify a command module and name.")
-            sys.exit(1)
-
-        cmd_module, cmd_name = args[:2]
-        from MoinMoin import wikiutil
-        plugin_class = wikiutil.importBuiltinPlugin('script.%s' % cmd_module, cmd_name, 'PluginScript')
-        plugin_class(args[2:], self.options).run() # all starts again there
-
--- a/MoinMoin/script/account/check.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/account/check.py	Sun May 21 12:44:52 2006 +0200
@@ -66,7 +66,7 @@
 
 import os
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 from MoinMoin import user, wikiutil
 
 class PluginScript(MoinScript):
--- a/MoinMoin/script/account/create.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/account/create.py	Sun May 21 12:44:52 2006 +0200
@@ -6,7 +6,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     def __init__(self, argv, def_values):
--- a/MoinMoin/script/account/disable.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/account/disable.py	Sun May 21 12:44:52 2006 +0200
@@ -6,7 +6,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     def __init__(self, argv, def_values):
--- a/MoinMoin/script/cli/show.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/cli/show.py	Sun May 21 12:44:52 2006 +0200
@@ -8,7 +8,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     """ show page script class """
--- a/MoinMoin/script/export/dump.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/export/dump.py	Sun May 21 12:44:52 2006 +0200
@@ -14,8 +14,7 @@
 import sys, os, time, StringIO, codecs, shutil, re, errno
 
 from MoinMoin import config, wikiutil, Page
-from MoinMoin.script import _util
-from MoinMoin.script._util import MoinScript
+from MoinMoin import script
 from MoinMoin.action import AttachFile
 
 url_prefix = "."
@@ -65,22 +64,22 @@
             try:
                 os.makedirs(dest_dir)
             except:
-                _util.fatal("Cannot create attachment directory '%s'" % dest_dir)
+                script.fatal("Cannot create attachment directory '%s'" % dest_dir)
         elif not os.path.isdir(dest_dir):
-            _util.fatal("'%s' is not a directory" % dest_dir)
+            script.fatal("'%s' is not a directory" % dest_dir)
 
         shutil.copyfile(source_file, dest_file)
-        _util.log('Writing "%s"...' % dest_url)
+        script.log('Writing "%s"...' % dest_url)
         return dest_url
     else:
         return ""
   
 
-class PluginScript(MoinScript):
+class PluginScript(script.MoinScript):
     """ Dump script class """
     
     def __init__(self, argv=None, def_values=None):
-        MoinScript.__init__(self, argv, def_values)
+        script.MoinScript.__init__(self, argv, def_values)
         self.parser.add_option(
             "-t", "--target-dir", dest="target_dir",
             help="Write html dump to DIRECTORY"
@@ -93,17 +92,17 @@
         outputdir = os.path.abspath(self.options.target_dir)
         try:
             os.mkdir(outputdir)
-            _util.log("Created output directory '%s'!" % outputdir)
+            script.log("Created output directory '%s'!" % outputdir)
         except OSError, err:
             if err.errno != errno.EEXIST:
-                _util.fatal("Cannot create output directory '%s'!" % outputdir)
+                script.fatal("Cannot create output directory '%s'!" % outputdir)
 
         # Insert config dir or the current directory to the start of the path.
         config_dir = self.options.config_dir
         if config_dir and os.path.isfile(config_dir):
             config_dir = os.path.dirname(config_dir)
         if config_dir and not os.path.isdir(config_dir):
-            _util.fatal("bad path given to --config-dir option")
+            script.fatal("bad path given to --config-dir option")
         sys.path.insert(0, os.path.abspath(config_dir or os.curdir))
 
         self.init_request()
@@ -138,7 +137,7 @@
         for pagename in pages:
             # we have the same name in URL and FS
             file = wikiutil.quoteWikinameURL(pagename) 
-            _util.log('Writing "%s"...' % file)
+            script.log('Writing "%s"...' % file)
             try:
                 pagehtml = ''
                 page = Page.Page(request, pagename)
--- a/MoinMoin/script/import/irclog.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/import/irclog.py	Sun May 21 12:44:52 2006 +0200
@@ -24,7 +24,7 @@
 import os
 
 from MoinMoin.PageEditor import PageEditor
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 def decodeLinewise(text):
     resultList = []
--- a/MoinMoin/script/lupy/build.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/lupy/build.py	Sun May 21 12:44:52 2006 +0200
@@ -11,8 +11,7 @@
 
 import os
 
-from MoinMoin.script import _util
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 from MoinMoin.request import RequestCLI
 from MoinMoin.lupy import Index
 
--- a/MoinMoin/script/maint/cleancache.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/maint/cleancache.py	Sun May 21 12:44:52 2006 +0200
@@ -20,7 +20,7 @@
 
 import os
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     def __init__(self, argv, def_values):
--- a/MoinMoin/script/maint/cleanpage.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/maint/cleanpage.py	Sun May 21 12:44:52 2006 +0200
@@ -10,7 +10,7 @@
 
 import os
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     def __init__(self, argv, def_values):
--- a/MoinMoin/script/maint/globaledit.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/maint/globaledit.py	Sun May 21 12:44:52 2006 +0200
@@ -12,7 +12,7 @@
 debug = False
 
 from MoinMoin import PageEditor
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     def __init__(self, argv, def_values):
--- a/MoinMoin/script/maint/mkpagepacks.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/maint/mkpagepacks.py	Sun May 21 12:44:52 2006 +0200
@@ -16,7 +16,7 @@
 from MoinMoin.Page import Page
 from MoinMoin.PageEditor import PageEditor
 from MoinMoin.packages import packLine, unpackLine, MOIN_PACKAGE_FILE
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 EXTRA = u'extra'
 NODIST = u'nodist'
--- a/MoinMoin/script/maint/reducewiki.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/maint/reducewiki.py	Sun May 21 12:44:52 2006 +0200
@@ -30,7 +30,7 @@
 from MoinMoin.Page import Page
 from MoinMoin.action import AttachFile
 
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     def __init__(self, argv, def_values):
--- a/MoinMoin/script/migration/data.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/migration/data.py	Sun May 21 12:44:52 2006 +0200
@@ -20,7 +20,7 @@
 import os
 
 from MoinMoin import wikiutil
-from MoinMoin.script._util import MoinScript
+from MoinMoin.script import MoinScript
 
 class PluginScript(MoinScript):
     """ Migration script class """
--- a/MoinMoin/script/moin.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/script/moin.py	Sun May 21 12:44:52 2006 +0200
@@ -11,8 +11,8 @@
 """
 
 def run():
-    from MoinMoin.script import _util
-    _util.MoinScript().run(showtime=0)
+    from MoinMoin.script import MoinScript
+    MoinScript().run(showtime=0)
     
 if __name__ == "__main__":
     # Insert the path to MoinMoin in the start of the path
--- a/MoinMoin/stats/chart.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/stats/chart.py	Sun May 21 12:44:52 2006 +0200
@@ -16,7 +16,7 @@
 """
 
 import gdchart
-from MoinMoin.webapi.color import Color
+from MoinMoin.util.web import Color
 
 
 class ChartData:
--- a/MoinMoin/util/parameterparser.py	Sun May 21 12:43:58 2006 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin macro parameter parser
-
-    parses a given parameter string and seperates
-    the single parameters and detects their type
-
-    Possible parameterstypes are:
-
-    Name      | short  | example
-    ----------------------------
-     Integer  | i      | -374
-     Float    | f      | 234.234 23.345E-23
-     String   | s      | 'Stri\'ng'
-     Boolean  | b      | 0 1 True false
-     Name     |        | case_sensitive | converted to string
-    
-    @copyright: 2004 by Florian Festi
-    @license: GNU GPL, see COPYING for details.
-"""
-
-import re, types
-
-class ParameterParser:
-
-    def __init__(self, pattern):
-        #parameter_re = "([^\"',]*(\"[^\"]*\"|'[^']*')?[^\"',]*)[,)]"
-        name = "(?P<%s>[a-zA-Z_][a-zA-Z0-9_]*)"
-        int_re = r"(?P<int>-?\d+)"
-        float_re = r"(?P<float>-?\d+\.\d+([eE][+-]?\d+)?)"
-        string_re = (r"(?P<string>('([^']|(\'))*?')|" +
-                                r'("([^"]|(\"))*?"))')
-        name_re = name % "name"
-        name_param_re = name % "name_param"
-
-        param_re = r"\s*(\s*%s\s*=\s*)?(%s|%s|%s|%s)\s*(,|$)" % (name_re,
-                                                          float_re,
-                                                          int_re,
-                                                          string_re,
-                                                          name_param_re)
-        self.param_re = re.compile(param_re, re.U)
-        self._parse_pattern(pattern)
-
-    def _parse_pattern(self, pattern):
-        param_re = r"(%(?P<name>\(.*?\))?(?P<type>[ifs]{1,3}))|\|"
-        i = 0
-        self.optional = -1
-        named = False
-        self.param_list = []
-        self.param_dict = {}
-        for match in re.finditer(param_re, pattern):
-            if match.group() == "|":
-                self.optional = i
-                continue
-            self.param_list.append(match.group('type'))
-            if match.group('name'):
-                named = True
-                self.param_dict[match.group('name')[1:-1]] = i
-            elif named:
-                raise ValueError, "Named parameter expected"
-            i += 1
-
-    def __str__(self):
-        return "%s, %s, optional:%s" % (self.param_list, self.param_dict,
-                                        self.optional)
-
-    def parse_parameters(self, input):
-        """
-        (4, 2)
-        """
-
-        parameter_list = [None] * len(self.param_list)
-        parameter_dict = {}
-        check_list = [0] * len(self.param_list)
-            
-        i = 0
-        start = 0
-        named = False
-        while start<len(input):
-            match = re.match(self.param_re, input[start:])
-            if not match: raise ValueError, "Misformatted value"
-            start += match.end()
-            value = None
-            if match.group("int"):
-                value = int(match.group("int"))
-                type = 'i'
-            elif match.group("float"):
-                value = float(match.group("float"))
-                type = 'f'
-            elif match.group("string"):
-                value = match.group("string")[1:-1]
-                type = 's'
-            elif match.group("name_param"):
-                value = match.group("name_param")
-                type = 'n'
-            else:
-                value = None
-
-            parameter_list.append(value)
-            if match.group("name"):
-                if not self.param_dict.has_key( match.group("name")):
-                    raise ValueError, "Unknown parameter name '%s'" % match.group("name")
-                nr = self.param_dict[match.group("name")]
-                if check_list[nr]:
-                    raise ValueError, "Parameter specified twice"
-                else:
-                    check_list[nr] = 1
-                parameter_dict[match.group("name")] = value
-                parameter_list[nr] = value
-                named = True
-            elif named:
-                raise ValueError, "Only named parameters allowed"
-            else:
-                nr = i
-                parameter_list[nr] = value
-            # check type
-            #if not type in self.param_list[nr]:
-
-                
-            i += 1
-        return parameter_list, parameter_dict
-
-
-    def _check_type(value, type, format):
-        if type == 'n' and 's' in format: # n as s
-            return value
-        
-        if type in format: return value # x -> x
-        
-        if type == 'i':
-            if 'f' in format: return float(value) # i -> f
-            elif 'b' in format: return value # i -> b
-        elif type == 'f':
-            if 'b' in format: return value  # f -> b
-        elif type == 's':
-            if 'b' in format:
-                return value.lower() != 'false' # s-> b
-
-
-        if 's' in format: # * -> s
-            return str(value) 
-        else:
-            pass # XXX error
-
-
-def main():
-    pattern = "%i%sf%s%ifs%(a)s|%(b)s"
-    param = ' 4,"DI\'NG", b=retry, a="DING"'
-
-    #p_list, p_dict = parse_parameters(param)
-    
-    print 'Pattern :', pattern
-    print 'Param :', param
-
-    P = ParameterParser(pattern)
-    print P
-    print P.parse_parameters(param)
-
-
-if __name__=="__main__":
-    main()
--- a/MoinMoin/util/web.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/util/web.py	Sun May 21 12:44:52 2006 +0200
@@ -6,7 +6,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import re
+import re, types
 from MoinMoin import config
 
 def getIntegerInput(request, fieldname, default=None, minval=None, maxval=None):
@@ -57,3 +57,199 @@
 
     return result
 
+
+class Color:
+    """ RGB-Triple that automatically converts from and to
+        "#RRGGBB" encoding, and also takes Netscape color names.
+        
+        The color values are stored in the attributes `r`, `g` and `b`.
+
+        Example:
+            >>> from color import Color
+            >>> Color('yellow')
+            Color(255, 255, 0)
+            >>> str(Color('yellow'))
+            '#FFFF00'
+            >>> str(Color((128, 0, 128)))
+            '#800080'
+            >>> Color('#FF00FF')
+            Color(255, 0, 255)
+    """
+
+    COLORS = {
+        'aliceblue': (0xF0, 0xF8, 0xFF),
+        'antiquewhite': (0xFA, 0xEB, 0xD7),
+        'aqua': (0x00, 0xFF, 0xFF),
+        'aquamarine': (0x7F, 0xFF, 0xD4),
+        'azure': (0xF0, 0xFF, 0xFF),
+        'beige': (0xF5, 0xF5, 0xDC),
+        'bisque': (0xFF, 0xE4, 0xC4),
+        'black': (0x00, 0x00, 0x00),
+        'blanchedalmond': (0xFF, 0xEB, 0xCD),
+        'blue': (0x00, 0x00, 0xFF),
+        'blueviolet': (0x8A, 0x2B, 0xE2),
+        'brown': (0xA5, 0x2A, 0x2A),
+        'burlywood': (0xDE, 0xB8, 0x87),
+        'cadetblue': (0x5F, 0x9E, 0xA0),
+        'chartreuse': (0x7F, 0xFF, 0x00),
+        'chocolate': (0xD2, 0x69, 0x1E),
+        'coral': (0xFF, 0x7F, 0x50),
+        'cornflowerblue': (0x64, 0x95, 0xED),
+        'cornsilk': (0xFF, 0xF8, 0xDC),
+        'crimson': (0xDC, 0x14, 0x3C),
+        'cyan': (0x00, 0xFF, 0xFF),
+        'darkblue': (0x00, 0x00, 0x8B),
+        'darkcyan': (0x00, 0x8B, 0x8B),
+        'darkgoldenrod': (0xB8, 0x86, 0x0B),
+        'darkgray': (0xA9, 0xA9, 0xA9),
+        'darkgreen': (0x00, 0x64, 0x00),
+        'darkkhaki': (0xBD, 0xB7, 0x6B),
+        'darkmagenta': (0x8B, 0x00, 0x8B),
+        'darkolivegreen': (0x55, 0x6B, 0x2F),
+        'darkorange': (0xFF, 0x8C, 0x00),
+        'darkorchid': (0x99, 0x32, 0xCC),
+        'darkred': (0x8B, 0x00, 0x00),
+        'darksalmon': (0xE9, 0x96, 0x7A),
+        'darkseagreen': (0x8F, 0xBC, 0x8F),
+        'darkslateblue': (0x48, 0x3D, 0x8B),
+        'darkslategray': (0x2F, 0x4F, 0x4F),
+        'darkturquoise': (0x00, 0xCE, 0xD1),
+        'darkviolet': (0x94, 0x00, 0xD3),
+        'deeppink': (0xFF, 0x14, 0x93),
+        'deepskyblue': (0x00, 0xBF, 0xFF),
+        'dimgray': (0x69, 0x69, 0x69),
+        'dodgerblue': (0x1E, 0x90, 0xFF),
+        'firebrick': (0xB2, 0x22, 0x22),
+        'floralwhite': (0xFF, 0xFA, 0xF0),
+        'forestgreen': (0x22, 0x8B, 0x22),
+        'fuchsia': (0xFF, 0x00, 0xFF),
+        'gainsboro': (0xDC, 0xDC, 0xDC),
+        'ghostwhite': (0xF8, 0xF8, 0xFF),
+        'gold': (0xFF, 0xD7, 0x00),
+        'goldenrod': (0xDA, 0xA5, 0x20),
+        'gray': (0x80, 0x80, 0x80),
+        'green': (0x00, 0x80, 0x00),
+        'greenyellow': (0xAD, 0xFF, 0x2F),
+        'honeydew': (0xF0, 0xFF, 0xF0),
+        'hotpink': (0xFF, 0x69, 0xB4),
+        'indianred': (0xCD, 0x5C, 0x5C),
+        'indigo': (0x4B, 0x00, 0x82),
+        'ivory': (0xFF, 0xFF, 0xF0),
+        'khaki': (0xF0, 0xE6, 0x8C),
+        'lavender': (0xE6, 0xE6, 0xFA),
+        'lavenderblush': (0xFF, 0xF0, 0xF5),
+        'lawngreen': (0x7C, 0xFC, 0x00),
+        'lemonchiffon': (0xFF, 0xFA, 0xCD),
+        'lightblue': (0xAD, 0xD8, 0xE6),
+        'lightcoral': (0xF0, 0x80, 0x80),
+        'lightcyan': (0xE0, 0xFF, 0xFF),
+        'lightgoldenrodyellow': (0xFA, 0xFA, 0xD2),
+        'lightgreen': (0x90, 0xEE, 0x90),
+        'lightgrey': (0xD3, 0xD3, 0xD3),
+        'lightpink': (0xFF, 0xB6, 0xC1),
+        'lightsalmon': (0xFF, 0xA0, 0x7A),
+        'lightseagreen': (0x20, 0xB2, 0xAA),
+        'lightskyblue': (0x87, 0xCE, 0xFA),
+        'lightslategray': (0x77, 0x88, 0x99),
+        'lightsteelblue': (0xB0, 0xC4, 0xDE),
+        'lightyellow': (0xFF, 0xFF, 0xE0),
+        'lime': (0x00, 0xFF, 0x00),
+        'limegreen': (0x32, 0xCD, 0x32),
+        'linen': (0xFA, 0xF0, 0xE6),
+        'magenta': (0xFF, 0x00, 0xFF),
+        'maroon': (0x80, 0x00, 0x00),
+        'mediumaquamarine': (0x66, 0xCD, 0xAA),
+        'mediumblue': (0x00, 0x00, 0xCD),
+        'mediumorchid': (0xBA, 0x55, 0xD3),
+        'mediumpurple': (0x93, 0x70, 0xDB),
+        'mediumseagreen': (0x3C, 0xB3, 0x71),
+        'mediumslateblue': (0x7B, 0x68, 0xEE),
+        'mediumspringgreen': (0x00, 0xFA, 0x9A),
+        'mediumturquoise': (0x48, 0xD1, 0xCC),
+        'mediumvioletred': (0xC7, 0x15, 0x85),
+        'midnightblue': (0x19, 0x19, 0x70),
+        'mintcream': (0xF5, 0xFF, 0xFA),
+        'mistyrose': (0xFF, 0xE4, 0xE1),
+        'moccasin': (0xFF, 0xE4, 0xB5),
+        'navajowhite': (0xFF, 0xDE, 0xAD),
+        'navy': (0x00, 0x00, 0x80),
+        'oldlace': (0xFD, 0xF5, 0xE6),
+        'olive': (0x80, 0x80, 0x00),
+        'olivedrab': (0x6B, 0x8E, 0x23),
+        'orange': (0xFF, 0xA5, 0x00),
+        'orangered': (0xFF, 0x45, 0x00),
+        'orchid': (0xDA, 0x70, 0xD6),
+        'palegoldenrod': (0xEE, 0xE8, 0xAA),
+        'palegreen': (0x98, 0xFB, 0x98),
+        'paleturquoise': (0xAF, 0xEE, 0xEE),
+        'palevioletred': (0xDB, 0x70, 0x93),
+        'papayawhip': (0xFF, 0xEF, 0xD5),
+        'peachpuff': (0xFF, 0xDA, 0xB9),
+        'peru': (0xCD, 0x85, 0x3F),
+        'pink': (0xFF, 0xC0, 0xCB),
+        'plum': (0xDD, 0xA0, 0xDD),
+        'powderblue': (0xB0, 0xE0, 0xE6),
+        'purple': (0x80, 0x00, 0x80),
+        'red': (0xFF, 0x00, 0x00),
+        'rosybrown': (0xBC, 0x8F, 0x8F),
+        'royalblue': (0x41, 0x69, 0xE1),
+        'saddlebrown': (0x8B, 0x45, 0x13),
+        'salmon': (0xFA, 0x80, 0x72),
+        'sandybrown': (0xF4, 0xA4, 0x60),
+        'seagreen': (0x2E, 0x8B, 0x57),
+        'seashell': (0xFF, 0xF5, 0xEE),
+        'sienna': (0xA0, 0x52, 0x2D),
+        'silver': (0xC0, 0xC0, 0xC0),
+        'skyblue': (0x87, 0xCE, 0xEB),
+        'slateblue': (0x6A, 0x5A, 0xCD),
+        'slategray': (0x70, 0x80, 0x90),
+        'snow': (0xFF, 0xFA, 0xFA),
+        'springgreen': (0x00, 0xFF, 0x7F),
+        'steelblue': (0x46, 0x82, 0xB4),
+        'tan': (0xD2, 0xB4, 0x8C),
+        'teal': (0x00, 0x80, 0x80),
+        'thistle': (0xD8, 0xBF, 0xD8),
+        'tomato': (0xFF, 0x63, 0x47),
+        'turquoise': (0x40, 0xE0, 0xD0),
+        'violet': (0xEE, 0x82, 0xEE),
+        'wheat': (0xF5, 0xDE, 0xB3),
+        'white': (0xFF, 0xFF, 0xFF),
+        'whitesmoke': (0xF5, 0xF5, 0xF5),
+        'yellow': (0xFF, 0xFF, 0x00),
+        'yellowgreen': (0x9A, 0xCD, 0x32),
+    }
+
+    def __init__(self, color):
+        """ Init color value, the 'color' parameter may be
+            another Color instance, a tuple containing 3 color values, 
+            a Netscape color name or a HTML color ("#RRGGBB").
+        """
+        if isinstance(color, types.TupleType) and len(color) == 3:
+            self.r, self.g, self.b = map(int, color)
+        elif isinstance(color, Color):
+            self.r, self.g, self.b = color.r, color.g, color.b
+        elif not isinstance(color, types.StringType):
+            raise TypeError("Color() expects a Color instance, a RGB triple or a color string")
+        elif color[0] == '#':
+            color = long(color[1:], 16)
+            self.r = (color >> 16) & 255
+            self.g = (color >> 8) & 255
+            self.b = color & 255
+        elif not self.COLORS.has_key(color):
+            raise ValueError("Unknown color name '%s'" % color)
+        else:
+            # known color name
+            self.r, self.g, self.b = self.COLORS[color]
+
+    def __str__(self):
+        return "#%02X%02X%02X" % (self.r, self.g, self.b)
+
+    def __repr__(self):
+        return "Color(%d, %d, %d)" % (self.r, self.g, self.b)
+
+    def __int__(self):
+        return self.__long__()
+
+    def __long__(self):
+        return (self.r << 16) | (self.g << 8) | self.b
+
--- a/MoinMoin/util/wikiext.py	Sun May 21 12:43:58 2006 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - Utilities for writing extensions
-
-    The stuff in this module is especially geared towards
-    writing extensions / plugins, i.e. additional actions,
-    macros, parsers and formatters.
-
-    See MoinMoin.wikiutil for more.
-
-    @copyright: 2002 by Jürgen Hermann <jh@web.de>
-    @license: GNU GPL, see COPYING for details.
-"""
-
-#############################################################################
-### Parameter parsing
-#############################################################################
-
-# !!! This is a lot like wikiutil.parseAttributes, and should be combined
-def parseParameters(parameters, arglist):
-    """ Parse a list of parameters and return a dict plus a possible
-        error message.
-
-        `parameters` is a string containing the actual arguments, while
-        `arglist` is a list with tuples of the expected parameter names
-        and their default value. This works identical to the call parameter
-        handling of Python/C (PyArg_ParseTupleAndKeywords).
-
-        Parameter names are case insensitive, and always returned in
-        lowercase form. `arglist` is expected to contain them in lowercase
-        form also.
-    """
-    import shlex, StringIO
-    # XXX FIXME we need _ here!
-    QUOTES = "\"'"
-    DIGITS = "0123456789"
-    parser = shlex.shlex(StringIO.StringIO(parameters))
-    parser.commenters = ''
-    msg = None
-    pos = 0 # if this gets -1, positional params are OFF
-    result = {}
-
-    while not msg:
-        key = parser.get_token()
-        val = None
-        if not key: break
-
-        if pos >= 0:
-            if key[0] in QUOTES:
-                val = key[1:-1]
-            elif key[0] in DIGITS:
-                val = key
-            pos += 1
-        
-        if val:
-            # !!!!!!!!!!!!!!!!!
-            pass
-        else:
-            eq = parser.get_token()
-            if eq != "=":
-                msg = _('Expected "=" to follow "%(token)s"') % {'token': key}
-                break
-
-            val = parser.get_token()
-            if not val:
-                msg = _('Expected a value for key "%(token)s"') % {'token': key}
-                break
-
-        """
-        -----------------------------
-        key = wikiutil.escape(key) # make sure nobody cheats
-
-        # safely escape and quote value
-        if val[0] in :
-            val = wikiutil.escape(val)
-        else:
-            val = '"%s"' % wikiutil.escape(val, 1)
-        """
-
-        result[key.lower()] = val
-
-    return result, msg or ''
-
--- a/MoinMoin/webapi/__init__.py	Sun May 21 12:43:58 2006 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - Interface to HTTP stuff
-
-    @copyright: 2001, 2002 by Jürgen Hermann <jh@web.de>
-    @license: GNU GPL, see COPYING for details.
-"""
-
-
--- a/MoinMoin/wikiutil.py	Sun May 21 12:43:58 2006 +0200
+++ b/MoinMoin/wikiutil.py	Sun May 21 12:44:52 2006 +0200
@@ -7,7 +7,7 @@
 """
     
 import os, re, difflib, urllib, cgi
-import codecs
+import codecs, types
 
 from MoinMoin import util, version, config
 from MoinMoin.util import pysupport, filesys
@@ -1026,7 +1026,6 @@
     @returns: the parser class or None
     """
     if not hasattr(cfg, '_EXT_TO_PARSER'):
-        import types
         etp, etd = {}, None
         for pname in getPlugins('parser', cfg):
             try:
@@ -1047,7 +1046,7 @@
 
 
 #############################################################################
-### Misc
+### Parameter parsing
 #############################################################################
 
 def parseAttributes(request, attrstring, endtoken=None, extension=None):
@@ -1126,6 +1125,164 @@
     return attrs, msg or ''
 
 
+class ParameterParser:
+    """ MoinMoin macro parameter parser
+
+        parses a given parameter string and seperates
+        the single parameters and detects their type
+
+        Possible parameterstypes are:
+
+        Name      | short  | example
+        ----------------------------
+         Integer  | i      | -374
+         Float    | f      | 234.234 23.345E-23
+         String   | s      | 'Stri\'ng'
+         Boolean  | b      | 0 1 True false
+         Name     |        | case_sensitive | converted to string
+        
+        @copyright: 2004 by Florian Festi
+        @license: GNU GPL, see COPYING for details.
+    """
+
+    def __init__(self, pattern):
+        #parameter_re = "([^\"',]*(\"[^\"]*\"|'[^']*')?[^\"',]*)[,)]"
+        name = "(?P<%s>[a-zA-Z_][a-zA-Z0-9_]*)"
+        int_re = r"(?P<int>-?\d+)"
+        float_re = r"(?P<float>-?\d+\.\d+([eE][+-]?\d+)?)"
+        string_re = (r"(?P<string>('([^']|(\'))*?')|" +
+                                r'("([^"]|(\"))*?"))')
+        name_re = name % "name"
+        name_param_re = name % "name_param"
+
+        param_re = r"\s*(\s*%s\s*=\s*)?(%s|%s|%s|%s)\s*(,|$)" % (
+                   name_re, float_re, int_re, string_re, name_param_re)
+        self.param_re = re.compile(param_re, re.U)
+        self._parse_pattern(pattern)
+
+    def _parse_pattern(self, pattern):
+        param_re = r"(%(?P<name>\(.*?\))?(?P<type>[ifs]{1,3}))|\|"
+        i = 0
+        self.optional = -1
+        named = False
+        self.param_list = []
+        self.param_dict = {}
+        for match in re.finditer(param_re, pattern):
+            if match.group() == "|":
+                self.optional = i
+                continue
+            self.param_list.append(match.group('type'))
+            if match.group('name'):
+                named = True
+                self.param_dict[match.group('name')[1:-1]] = i
+            elif named:
+                raise ValueError, "Named parameter expected"
+            i += 1
+
+    def __str__(self):
+        return "%s, %s, optional:%s" % (self.param_list, self.param_dict,
+                                        self.optional)
+
+    def parse_parameters(self, input):
+        """
+        (4, 2)
+        """
+
+        parameter_list = [None] * len(self.param_list)
+        parameter_dict = {}
+        check_list = [0] * len(self.param_list)
+            
+        i = 0
+        start = 0
+        named = False
+        while start<len(input):
+            match = re.match(self.param_re, input[start:])
+            if not match: raise ValueError, "Misformatted value"
+            start += match.end()
+            value = None
+            if match.group("int"):
+                value = int(match.group("int"))
+                type = 'i'
+            elif match.group("float"):
+                value = float(match.group("float"))
+                type = 'f'
+            elif match.group("string"):
+                value = match.group("string")[1:-1]
+                type = 's'
+            elif match.group("name_param"):
+                value = match.group("name_param")
+                type = 'n'
+            else:
+                value = None
+
+            parameter_list.append(value)
+            if match.group("name"):
+                if not self.param_dict.has_key( match.group("name")):
+                    raise ValueError, "Unknown parameter name '%s'" % match.group("name")
+                nr = self.param_dict[match.group("name")]
+                if check_list[nr]:
+                    raise ValueError, "Parameter specified twice"
+                else:
+                    check_list[nr] = 1
+                parameter_dict[match.group("name")] = value
+                parameter_list[nr] = value
+                named = True
+            elif named:
+                raise ValueError, "Only named parameters allowed"
+            else:
+                nr = i
+                parameter_list[nr] = value
+            # check type
+            #if not type in self.param_list[nr]:
+
+                
+            i += 1
+        return parameter_list, parameter_dict
+
+
+    def _check_type(value, type, format):
+        if type == 'n' and 's' in format: # n as s
+            return value
+        
+        if type in format: return value # x -> x
+        
+        if type == 'i':
+            if 'f' in format: return float(value) # i -> f
+            elif 'b' in format: return value # i -> b
+        elif type == 'f':
+            if 'b' in format: return value  # f -> b
+        elif type == 's':
+            if 'b' in format:
+                return value.lower() != 'false' # s-> b
+
+
+        if 's' in format: # * -> s
+            return str(value) 
+        else:
+            pass # XXX error
+
+"""
+def main():
+    pattern = "%i%sf%s%ifs%(a)s|%(b)s"
+    param = ' 4,"DI\'NG", b=retry, a="DING"'
+
+    #p_list, p_dict = parse_parameters(param)
+    
+    print 'Pattern :', pattern
+    print 'Param :', param
+
+    P = ParameterParser(pattern)
+    print P
+    print P.parse_parameters(param)
+
+
+if __name__=="__main__":
+    main()
+"""
+
+#############################################################################
+### Misc
+#############################################################################
 def taintfilename(basename):
     """
     Make a filename that is supposed to be a plain name secure, i.e.