Back to index

moin  1.9.0~rc2
__init__.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - Extension Script Package
00004 
00005     @copyright: 2000-2002 Juergen Hermann <jh@web.de>,
00006                 2006 MoinMoin:ThomasWaldmann
00007     @license: GNU GPL, see COPYING for details.
00008 """
00009 
00010 import os, sys, time
00011 from StringIO import StringIO
00012 
00013 flag_quiet = 0
00014 
00015 # ScriptRequest -----------------------------------------------------------
00016 
00017 class ScriptRequest(object):
00018     """this is for scripts (MoinMoin/script/*) running from the commandline (CLI)
00019        or from the xmlrpc server (triggered by a remote xmlrpc client).
00020 
00021        Every script needs to do IO using this ScriptRequest class object -
00022        IT IS DIFFERENT from the usual "request" you have in moin (easily to be seen
00023        when you look at an xmlrpc script invocation: request.write will write to the
00024        xmlrpc "channel", but scriptrequest.write needs to write to some buffer we
00025        transmit later as an xmlrpc function return value.
00026     """
00027     def __init__(self, instream, outstream, errstream):
00028         self.instream = instream
00029         self.outstream = outstream
00030         self.errstream = errstream
00031 
00032     def read(self, n=None):
00033         if n is None:
00034             data = self.instream.read()
00035         else:
00036             data = self.instream.read(n)
00037         return data
00038 
00039     def write(self, data):
00040         self.outstream.write(data)
00041 
00042     def write_err(self, data):
00043         self.errstream.write(data)
00044 
00045 
00046 class ScriptRequestCLI(ScriptRequest):
00047     """ When a script runs directly on the shell, we just use the CLI request
00048         object (see MoinMoin.request.request_cli) to do I/O (which will use stdin/out/err).
00049     """
00050     def __init__(self, request):
00051         self.request = request
00052 
00053     def read(self, n=None):
00054         return self.request.read(n)
00055 
00056     def write(self, data):
00057         return self.request.write(data)
00058 
00059     def write_err(self, data):
00060         return self.request.write(data) # XXX use correct request method - log, error, whatever.
00061 
00062 class ScriptRequestStrings(ScriptRequest):
00063     """ When a script gets run by our xmlrpc server, we have the input as a
00064         string and we also need to catch the output / error output as strings.
00065     """
00066     def __init__(self, instr):
00067         self.instream = StringIO(instr)
00068         self.outstream = StringIO()
00069         self.errstream = StringIO()
00070 
00071     def fetch_output(self):
00072         outstr = self.outstream.get_value()
00073         errstr = self.errstream.get_value()
00074         self.outstream.close()
00075         self.errstream.close()
00076         return outstr, errstr
00077 
00078 
00079 # Logging -----------------------------------------------------------------
00080 
00081 def fatal(msgtext, **kw):
00082     """ Print error msg to stderr and exit. """
00083     sys.stderr.write("\n\nFATAL ERROR: " + msgtext + "\n")
00084     sys.exit(1)
00085 
00086 
00087 def log(msgtext):
00088     """ Optionally print error msg to stderr. """
00089     if not flag_quiet:
00090         sys.stderr.write(msgtext + "\n")
00091 
00092 
00093 # Commandline Support --------------------------------------------------------
00094 
00095 class Script:
00096     def __init__(self, cmd, usage, argv=None, def_values=None):
00097         #print "argv:", argv, "def_values:", repr(def_values)
00098         if argv is None:
00099             self.argv = sys.argv[1:]
00100         else:
00101             self.argv = argv
00102         self.def_values = def_values
00103 
00104         global _start_time
00105         _start_time = time.clock()
00106 
00107         import optparse
00108         from MoinMoin import version
00109 
00110         rev = "%s %s [%s]" % (version.project, version.release, version.revision)
00111         sys.argv[0] = cmd
00112 
00113         self.parser = optparse.OptionParser(
00114             usage="%(cmd)s [command] %(usage)s" % {'cmd': os.path.basename(sys.argv[0]), 'usage': usage, },
00115             version=rev, add_help_option=False)
00116         self.parser.allow_interspersed_args = False
00117         if def_values:
00118             self.parser.set_defaults(**def_values.__dict__)
00119         self.parser.add_option(
00120             "-q", "--quiet",
00121             action="store_true", dest="quiet",
00122             help="Be quiet (no informational messages)"
00123         )
00124         self.parser.add_option(
00125             "--show-timing",
00126             action="store_true", dest="show_timing", default=False,
00127             help="Show timing values [default: False]"
00128         )
00129 
00130     def run(self, showtime=1):
00131         """ Run the main function of a command. """
00132         global flag_quiet
00133         try:
00134             try:
00135                 self.options, self.args = self.parser.parse_args(self.argv)
00136                 flag_quiet = self.options.quiet
00137                 # ToDo check if we need to initialize request (self.init_request())
00138                 self.mainloop()
00139             except KeyboardInterrupt:
00140                 log("*** Interrupted by user!")
00141             except SystemExit:
00142                 showtime = 0
00143                 raise
00144         finally:
00145             if showtime:
00146                 self.logRuntime()
00147 
00148     def logRuntime(self):
00149         """ Print the total command run time. """
00150         if self.options.show_timing:
00151             log("Needed %.3f secs." % (time.clock() - _start_time, ))
00152 
00153 
00154 class MoinScript(Script):
00155     """ Moin main script class """
00156 
00157     def __init__(self, argv=None, def_values=None):
00158         Script.__init__(self, "moin", "[general options] command subcommand [specific options]", argv, def_values)
00159         # those are options potentially useful for all sub-commands:
00160         self.parser.add_option(
00161             "--config-dir", metavar="DIR", dest="config_dir",
00162             help=("Path to the directory containing the wiki "
00163                   "configuration files. [default: current directory]")
00164         )
00165         self.parser.add_option(
00166             "--wiki-url", metavar="WIKIURL", dest="wiki_url",
00167             help="URL of a single wiki to migrate e.g. http://localhost/mywiki/ [default: CLI]"
00168         )
00169         self.parser.add_option(
00170             "--page", dest="page", default='',
00171             help="wiki page name [default: all pages]"
00172         )
00173 
00174     def init_request(self):
00175         """ create request """
00176         from MoinMoin.web.contexts import ScriptContext
00177         url = self.options.wiki_url or None
00178         self.request = ScriptContext(url, self.options.page)
00179 
00180     def mainloop(self):
00181         # Insert config dir or the current directory to the start of the path.
00182         config_dir = self.options.config_dir
00183         if config_dir:
00184             if os.path.isdir(config_dir):
00185                 sys.path.insert(0, os.path.abspath(config_dir))
00186             else:
00187                 fatal("bad path given to --config-dir option")
00188 
00189         args = self.args
00190         if len(args) < 2:
00191             self.parser.print_help()
00192             fatal("""You must specify a command module and name:
00193 
00194 moin ... account check ...
00195 moin ... account create ...
00196 moin ... account disable ...
00197 moin ... account resetpw ...
00198 
00199 moin ... cli show ...
00200 
00201 moin ... export dump ...
00202 
00203 moin ... import irclog ...
00204 
00205 moin ... index build ...
00206 
00207 moin ... maint cleancache ...
00208 moin ... maint cleanpage ...
00209 moin ... maint globaledit ...
00210 moin ... maint makecache ...
00211 moin ... maint mkpagepacks ...
00212 moin ... maint reducewiki ...
00213 
00214 moin ... migration data ...
00215 
00216 moin ... server standalone ...
00217 
00218 moin ... xmlrpc mailimport ...
00219 moin ... xmlrpc remote ...
00220 
00221 General options:
00222     Most commands need some general parameters before command subcommand:
00223     --config-dir=/config/directory
00224         Mandatory for most commands and specifies the directory that contains
00225         your wikiconfig.py (or farmconfig.py).
00226 
00227     --wiki-url=wiki.example.org/
00228         Mandatory for most commands and specifies the url of the wiki you like
00229         to operate on.
00230 
00231 Specific options:
00232     Most commands need additional parameters after command subcommand.
00233 
00234     To obtain additonal help on a command use 'moin module subcommand --help'
00235 """)
00236 
00237         cmd_module, cmd_name = args[:2]
00238         from MoinMoin import wikiutil
00239         try:
00240             plugin_class = wikiutil.importBuiltinPlugin('script.%s' % cmd_module, cmd_name, 'PluginScript')
00241         except wikiutil.PluginMissingError:
00242             fatal("Command plugin %r, command %r was not found." % (cmd_module, cmd_name))
00243 
00244         # We have to use the args list here instead of optparse, as optparse only
00245         # deals with things coming before command subcommand.
00246         if "--help" in args or "-h" in args:
00247             print "MoinMoin Help - %s/ %s\n" % (cmd_module, cmd_name)
00248             print plugin_class.__doc__
00249             print "Command line reference:"
00250             print "======================="
00251             plugin_class(args[2:], self.options).parser.print_help()
00252         else:
00253             plugin_class(args[2:], self.options).run() # all starts again there
00254