| Index: third_party/twisted_8_1/twisted/application/app.py
|
| diff --git a/third_party/twisted_8_1/twisted/application/app.py b/third_party/twisted_8_1/twisted/application/app.py
|
| deleted file mode 100644
|
| index 3bc841d410b4c12ee435f90f1c587a633e3618fa..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/application/app.py
|
| +++ /dev/null
|
| @@ -1,653 +0,0 @@
|
| -# -*- test-case-name: twisted.test.test_application,twisted.test.test_twistd -*-
|
| -# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -import sys, os, pdb, getpass, traceback, signal, warnings
|
| -
|
| -from twisted.python import runtime, log, usage, failure, util, logfile
|
| -from twisted.persisted import sob
|
| -from twisted.application import service, reactors
|
| -from twisted.internet import defer
|
| -from twisted import copyright
|
| -
|
| -# Expose the new implementation of installReactor at the old location.
|
| -from twisted.application.reactors import installReactor
|
| -from twisted.application.reactors import NoSuchReactor
|
| -
|
| -
|
| -
|
| -class _BasicProfiler(object):
|
| - """
|
| - @ivar saveStats: if C{True}, save the stats information instead of the
|
| - human readable format
|
| - @type saveStats: C{bool}
|
| -
|
| - @ivar profileOutput: the name of the file use to print profile data.
|
| - @type profileOutput: C{str}
|
| - """
|
| -
|
| - def __init__(self, profileOutput, saveStats):
|
| - self.profileOutput = profileOutput
|
| - self.saveStats = saveStats
|
| -
|
| -
|
| - def _reportImportError(self, module, e):
|
| - """
|
| - Helper method to report an import error with a profile module. This
|
| - has to be explicit because some of these modules are removed by
|
| - distributions due to them being non-free.
|
| - """
|
| - s = "Failed to import module %s: %s" % (module, e)
|
| - s += """
|
| -This is most likely caused by your operating system not including
|
| -the module due to it being non-free. Either do not use the option
|
| ---profile, or install the module; your operating system vendor
|
| -may provide it in a separate package.
|
| -"""
|
| - raise SystemExit(s)
|
| -
|
| -
|
| -
|
| -class ProfileRunner(_BasicProfiler):
|
| - """
|
| - Runner for the standard profile module.
|
| - """
|
| -
|
| - def run(self, reactor):
|
| - """
|
| - Run reactor under the standard profiler.
|
| - """
|
| - try:
|
| - import profile
|
| - except ImportError, e:
|
| - self._reportImportError("profile", e)
|
| -
|
| - p = profile.Profile()
|
| - p.runcall(reactor.run)
|
| - if self.saveStats:
|
| - p.dump_stats(self.profileOutput)
|
| - else:
|
| - tmp, sys.stdout = sys.stdout, open(self.profileOutput, 'a')
|
| - try:
|
| - p.print_stats()
|
| - finally:
|
| - sys.stdout, tmp = tmp, sys.stdout
|
| - tmp.close()
|
| -
|
| -
|
| -
|
| -class HotshotRunner(_BasicProfiler):
|
| - """
|
| - Runner for the hotshot profile module.
|
| - """
|
| -
|
| - def run(self, reactor):
|
| - """
|
| - Run reactor under the hotshot profiler.
|
| - """
|
| - try:
|
| - import hotshot.stats
|
| - except (ImportError, SystemExit), e:
|
| - # Certain versions of Debian (and Debian derivatives) raise
|
| - # SystemExit when importing hotshot if the "non-free" profiler
|
| - # module is not installed. Someone eventually recognized this
|
| - # as a bug and changed the Debian packaged Python to raise
|
| - # ImportError instead. Handle both exception types here in
|
| - # order to support the versions of Debian which have this
|
| - # behavior. The bug report which prompted the introduction of
|
| - # this highly undesirable behavior should be available online at
|
| - # <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=334067>.
|
| - # There seems to be no corresponding bug report which resulted
|
| - # in the behavior being removed. -exarkun
|
| - self._reportImportError("hotshot", e)
|
| -
|
| - # this writes stats straight out
|
| - p = hotshot.Profile(self.profileOutput)
|
| - p.runcall(reactor.run)
|
| - if self.saveStats:
|
| - # stats are automatically written to file, nothing to do
|
| - return
|
| - else:
|
| - s = hotshot.stats.load(self.profileOutput)
|
| - s.strip_dirs()
|
| - s.sort_stats(-1)
|
| - if getattr(s, 'stream', None) is not None:
|
| - # Python 2.5 and above supports a stream attribute
|
| - s.stream = open(self.profileOutput, 'w')
|
| - s.print_stats()
|
| - s.stream.close()
|
| - else:
|
| - # But we have to use a trick for Python < 2.5
|
| - tmp, sys.stdout = sys.stdout, open(self.profileOutput, 'w')
|
| - try:
|
| - s.print_stats()
|
| - finally:
|
| - sys.stdout, tmp = tmp, sys.stdout
|
| - tmp.close()
|
| -
|
| -
|
| -
|
| -class CProfileRunner(_BasicProfiler):
|
| - """
|
| - Runner for the cProfile module.
|
| - """
|
| -
|
| - def run(self, reactor):
|
| - """
|
| - Run reactor under the cProfile profiler.
|
| - """
|
| - try:
|
| - import cProfile, pstats
|
| - except ImportError, e:
|
| - self._reportImportError("cProfile", e)
|
| -
|
| - p = cProfile.Profile()
|
| - p.runcall(reactor.run)
|
| - if self.saveStats:
|
| - p.dump_stats(self.profileOutput)
|
| - else:
|
| - stream = open(self.profileOutput, 'w')
|
| - s = pstats.Stats(p, stream=stream)
|
| - s.strip_dirs()
|
| - s.sort_stats(-1)
|
| - s.print_stats()
|
| - stream.close()
|
| -
|
| -
|
| -
|
| -class AppProfiler(object):
|
| - """
|
| - Class which selects a specific profile runner based on configuration
|
| - options.
|
| -
|
| - @ivar profiler: the name of the selected profiler.
|
| - @type profiler: C{str}
|
| - """
|
| - profilers = {"profile": ProfileRunner, "hotshot": HotshotRunner,
|
| - "cProfile": CProfileRunner}
|
| -
|
| - def __init__(self, options):
|
| - saveStats = options.get("savestats", False)
|
| - profileOutput = options.get("profile", None)
|
| - self.profiler = options.get("profiler", None)
|
| - if options.get("nothotshot", False):
|
| - warnings.warn("The --nothotshot option is deprecated. Please "
|
| - "specify the profiler name using the --profiler "
|
| - "option", category=DeprecationWarning)
|
| - self.profiler = "profile"
|
| - if self.profiler in self.profilers:
|
| - profiler = self.profilers[self.profiler](profileOutput, saveStats)
|
| - self.run = profiler.run
|
| - else:
|
| - raise SystemExit("Unsupported profiler name: %s" % (self.profiler,))
|
| -
|
| -
|
| -
|
| -def runWithProfiler(reactor, config):
|
| - """
|
| - DEPRECATED in Twisted 8.0.
|
| -
|
| - Run reactor under standard profiler.
|
| - """
|
| - warnings.warn("runWithProfiler is deprecated since Twisted 8.0. "
|
| - "Use ProfileRunner instead.", DeprecationWarning, 2)
|
| - item = AppProfiler(config)
|
| - return item.run(reactor)
|
| -
|
| -
|
| -
|
| -def runWithHotshot(reactor, config):
|
| - """
|
| - DEPRECATED in Twisted 8.0.
|
| -
|
| - Run reactor under hotshot profiler.
|
| - """
|
| - warnings.warn("runWithHotshot is deprecated since Twisted 8.0. "
|
| - "Use HotshotRunner instead.", DeprecationWarning, 2)
|
| - item = AppProfiler(config)
|
| - return item.run(reactor)
|
| -
|
| -
|
| -
|
| -def fixPdb():
|
| - def do_stop(self, arg):
|
| - self.clear_all_breaks()
|
| - self.set_continue()
|
| - from twisted.internet import reactor
|
| - reactor.callLater(0, reactor.stop)
|
| - return 1
|
| -
|
| - def help_stop(self):
|
| - print """stop - Continue execution, then cleanly shutdown the twisted reactor."""
|
| -
|
| - def set_quit(self):
|
| - os._exit(0)
|
| -
|
| - pdb.Pdb.set_quit = set_quit
|
| - pdb.Pdb.do_stop = do_stop
|
| - pdb.Pdb.help_stop = help_stop
|
| -
|
| -
|
| -
|
| -def runReactorWithLogging(config, oldstdout, oldstderr, profiler=None, reactor=None):
|
| - """
|
| - Start the reactor, using profiling if specified by the configuration, and
|
| - log any error happening in the process.
|
| -
|
| - @param config: configuration of the twistd application.
|
| - @type config: L{ServerOptions}
|
| -
|
| - @param oldstdout: initial value of C{sys.stdout}.
|
| - @type oldstdout: C{file}
|
| -
|
| - @param oldstderr: initial value of C{sys.stderr}.
|
| - @type oldstderr: C{file}
|
| -
|
| - @param profiler: object used to run the reactor with profiling.
|
| - @type profiler: L{AppProfiler}
|
| -
|
| - @param reactor: The reactor to use. If C{None}, the global reactor will
|
| - be used.
|
| - """
|
| - if reactor is None:
|
| - from twisted.internet import reactor
|
| - try:
|
| - if config['profile']:
|
| - if profiler is not None:
|
| - profiler.run(reactor)
|
| - else:
|
| - # Backward compatible code
|
| - if not config['nothotshot']:
|
| - runWithHotshot(reactor, config)
|
| - else:
|
| - runWithProfiler(reactor, config)
|
| - elif config['debug']:
|
| - sys.stdout = oldstdout
|
| - sys.stderr = oldstderr
|
| - if runtime.platformType == 'posix':
|
| - signal.signal(signal.SIGUSR2, lambda *args: pdb.set_trace())
|
| - signal.signal(signal.SIGINT, lambda *args: pdb.set_trace())
|
| - fixPdb()
|
| - pdb.runcall(reactor.run)
|
| - else:
|
| - reactor.run()
|
| - except:
|
| - if config['nodaemon']:
|
| - file = oldstdout
|
| - else:
|
| - file = open("TWISTD-CRASH.log",'a')
|
| - traceback.print_exc(file=file)
|
| - file.flush()
|
| -
|
| -
|
| -
|
| -def getPassphrase(needed):
|
| - if needed:
|
| - return getpass.getpass('Passphrase: ')
|
| - else:
|
| - return None
|
| -
|
| -
|
| -
|
| -def getSavePassphrase(needed):
|
| - if needed:
|
| - passphrase = util.getPassword("Encryption passphrase: ")
|
| - else:
|
| - return None
|
| -
|
| -
|
| -
|
| -class ApplicationRunner(object):
|
| - """
|
| - An object which helps running an application based on a config object.
|
| -
|
| - Subclass me and implement preApplication and postApplication
|
| - methods. postApplication generally will want to run the reactor
|
| - after starting the application.
|
| -
|
| - @ivar config: The config object, which provides a dict-like interface.
|
| -
|
| - @ivar application: Available in postApplication, but not
|
| - preApplication. This is the application object.
|
| -
|
| - @ivar profilerFactory: Factory for creating a profiler object, able to
|
| - profile the application if options are set accordingly.
|
| -
|
| - @ivar profiler: Instance provided by C{profilerFactory}.
|
| - """
|
| - profilerFactory = AppProfiler
|
| -
|
| - def __init__(self, config):
|
| - self.config = config
|
| - self.profiler = self.profilerFactory(config)
|
| -
|
| -
|
| - def run(self):
|
| - """
|
| - Run the application.
|
| - """
|
| - self.preApplication()
|
| - self.application = self.createOrGetApplication()
|
| -
|
| - # Later, try adapting self.application to ILogObserverFactory or
|
| - # whatever and getting an observer from it, instead. Fall back to
|
| - # self.getLogObserver if the adaption fails.
|
| - self.startLogging(self.getLogObserver())
|
| -
|
| - self.postApplication()
|
| -
|
| -
|
| - def startReactor(self, reactor, oldstdout, oldstderr):
|
| - """
|
| - Run the reactor with the given configuration. Subclasses should
|
| - probably call this from C{postApplication}.
|
| -
|
| - @see: L{runReactorWithLogging}
|
| - """
|
| - runReactorWithLogging(
|
| - self.config, oldstdout, oldstderr, self.profiler, reactor)
|
| -
|
| -
|
| - def preApplication(self):
|
| - """
|
| - Override in subclass.
|
| -
|
| - This should set up any state necessary before loading and
|
| - running the Application.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| -
|
| - def startLogging(self, observer):
|
| - """
|
| - Initialize the logging system.
|
| -
|
| - @param observer: The observer to add to the logging system.
|
| - """
|
| - log.startLoggingWithObserver(observer)
|
| - sys.stdout.flush()
|
| - initialLog()
|
| -
|
| -
|
| - def getLogObserver(self):
|
| - """
|
| - Create a log observer to be added to the logging system before running
|
| - this application.
|
| - """
|
| - raise NotImplementedError()
|
| -
|
| -
|
| - def postApplication(self):
|
| - """
|
| - Override in subclass.
|
| -
|
| - This will be called after the application has been loaded (so
|
| - the C{application} attribute will be set). Generally this
|
| - should start the application and run the reactor.
|
| - """
|
| - raise NotImplementedError
|
| -
|
| -
|
| - def createOrGetApplication(self):
|
| - """
|
| - Create or load an Application based on the parameters found in the
|
| - given L{ServerOptions} instance.
|
| -
|
| - If a subcommand was used, the L{service.IServiceMaker} that it
|
| - represents will be used to construct a service to be added to
|
| - a newly-created Application.
|
| -
|
| - Otherwise, an application will be loaded based on parameters in
|
| - the config.
|
| - """
|
| - if self.config.subCommand:
|
| - # If a subcommand was given, it's our responsibility to create
|
| - # the application, instead of load it from a file.
|
| -
|
| - # loadedPlugins is set up by the ServerOptions.subCommands
|
| - # property, which is iterated somewhere in the bowels of
|
| - # usage.Options.
|
| - plg = self.config.loadedPlugins[self.config.subCommand]
|
| - ser = plg.makeService(self.config.subOptions)
|
| - application = service.Application(plg.tapname)
|
| - ser.setServiceParent(application)
|
| - else:
|
| - passphrase = getPassphrase(self.config['encrypted'])
|
| - application = getApplication(self.config, passphrase)
|
| - return application
|
| -
|
| -
|
| -
|
| -def getApplication(config, passphrase):
|
| - s = [(config[t], t)
|
| - for t in ['python', 'xml', 'source', 'file'] if config[t]][0]
|
| - filename, style = s[0], {'file':'pickle'}.get(s[1],s[1])
|
| - try:
|
| - log.msg("Loading %s..." % filename)
|
| - application = service.loadApplication(filename, style, passphrase)
|
| - log.msg("Loaded.")
|
| - except Exception, e:
|
| - s = "Failed to load application: %s" % e
|
| - if isinstance(e, KeyError) and e.args[0] == "application":
|
| - s += """
|
| -Could not find 'application' in the file. To use 'twistd -y', your .tac
|
| -file must create a suitable object (e.g., by calling service.Application())
|
| -and store it in a variable named 'application'. twistd loads your .tac file
|
| -and scans the global variables for one of this name.
|
| -
|
| -Please read the 'Using Application' HOWTO for details.
|
| -"""
|
| - traceback.print_exc(file=log.logfile)
|
| - log.msg(s)
|
| - log.deferr()
|
| - sys.exit('\n' + s + '\n')
|
| - return application
|
| -
|
| -
|
| -
|
| -def reportProfile(report_profile, name):
|
| - """
|
| - DEPRECATED since Twisted 8.0. This does nothing.
|
| - """
|
| - warnings.warn("reportProfile is deprecated and a no-op since Twisted 8.0.",
|
| - category=DeprecationWarning)
|
| -
|
| -
|
| -
|
| -def _reactorZshAction():
|
| - return "(%s)" % " ".join([r.shortName for r in reactors.getReactorTypes()])
|
| -
|
| -class ReactorSelectionMixin:
|
| - """
|
| - Provides options for selecting a reactor to install.
|
| - """
|
| - zsh_actions = {"reactor" : _reactorZshAction}
|
| - messageOutput = sys.stdout
|
| -
|
| -
|
| - def opt_help_reactors(self):
|
| - """
|
| - Display a list of possibly available reactor names.
|
| - """
|
| - for r in reactors.getReactorTypes():
|
| - self.messageOutput.write(' %-4s\t%s\n' %
|
| - (r.shortName, r.description))
|
| - raise SystemExit(0)
|
| -
|
| -
|
| - def opt_reactor(self, shortName):
|
| - """
|
| - Which reactor to use (see --help-reactors for a list of possibilities)
|
| - """
|
| - # Actually actually actually install the reactor right at this very
|
| - # moment, before any other code (for example, a sub-command plugin)
|
| - # runs and accidentally imports and installs the default reactor.
|
| - #
|
| - # This could probably be improved somehow.
|
| - try:
|
| - installReactor(shortName)
|
| - except NoSuchReactor:
|
| - msg = ("The specified reactor does not exist: '%s'.\n"
|
| - "See the list of available reactors with "
|
| - "--help-reactors" % (shortName,))
|
| - raise usage.UsageError(msg)
|
| - except Exception, e:
|
| - msg = ("The specified reactor cannot be used, failed with error: "
|
| - "%s.\nSee the list of available reactors with "
|
| - "--help-reactors" % (e,))
|
| - raise usage.UsageError(msg)
|
| - opt_r = opt_reactor
|
| -
|
| -
|
| -
|
| -
|
| -class ServerOptions(usage.Options, ReactorSelectionMixin):
|
| -
|
| - optFlags = [['savestats', None,
|
| - "save the Stats object rather than the text output of "
|
| - "the profiler."],
|
| - ['no_save','o', "do not save state on shutdown"],
|
| - ['encrypted', 'e',
|
| - "The specified tap/aos/xml file is encrypted."],
|
| - ['nothotshot', None,
|
| - "DEPRECATED. Don't use the 'hotshot' profiler even if "
|
| - "it's available."]]
|
| -
|
| - optParameters = [['logfile','l', None,
|
| - "log to a specified file, - for stdout"],
|
| - ['profile', 'p', None,
|
| - "Run in profile mode, dumping results to specified file"],
|
| - ['profiler', None, "hotshot",
|
| - "Name of the profiler to use, 'hotshot' or 'profile'."],
|
| - ['file','f','twistd.tap',
|
| - "read the given .tap file"],
|
| - ['python','y', None,
|
| - "read an application from within a Python file (implies -o)"],
|
| - ['xml', 'x', None,
|
| - "Read an application from a .tax file "
|
| - "(Marmalade format)."],
|
| - ['source', 's', None,
|
| - "Read an application from a .tas file (AOT format)."],
|
| - ['rundir','d','.',
|
| - 'Change to a supplied directory before running'],
|
| - ['report-profile', None, None,
|
| - 'E-mail address to use when reporting dynamic execution '
|
| - 'profiler stats. This should not be combined with '
|
| - 'other profiling options. This will only take effect '
|
| - 'if the application to be run has an application '
|
| - 'name.']]
|
| -
|
| - #zsh_altArgDescr = {"foo":"use this description for foo instead"}
|
| - #zsh_multiUse = ["foo", "bar"]
|
| - zsh_mutuallyExclusive = [("file", "python", "xml", "source")]
|
| - zsh_actions = {"file":'_files -g "*.tap"',
|
| - "python":'_files -g "*.(tac|py)"',
|
| - "xml":'_files -g "*.tax"',
|
| - "source":'_files -g "*.tas"',
|
| - "rundir":"_dirs"}
|
| - #zsh_actionDescr = {"logfile":"log file name", "random":"random seed"}
|
| -
|
| - def __init__(self, *a, **kw):
|
| - self['debug'] = False
|
| - usage.Options.__init__(self, *a, **kw)
|
| -
|
| - def opt_debug(self):
|
| - """
|
| - run the application in the Python Debugger (implies nodaemon),
|
| - sending SIGUSR2 will drop into debugger
|
| - """
|
| - defer.setDebugging(True)
|
| - failure.startDebugMode()
|
| - self['debug'] = True
|
| - opt_b = opt_debug
|
| -
|
| -
|
| - def opt_spew(self):
|
| - """Print an insanely verbose log of everything that happens.
|
| - Useful when debugging freezes or locks in complex code."""
|
| - sys.settrace(util.spewer)
|
| - try:
|
| - import threading
|
| - except ImportError:
|
| - return
|
| - threading.settrace(util.spewer)
|
| -
|
| -
|
| - def opt_report_profile(self, value):
|
| - """
|
| - DEPRECATED.
|
| -
|
| - Manage --report-profile option, which does nothing currently.
|
| - """
|
| - warnings.warn("--report-profile option is deprecated and a no-op "
|
| - "since Twisted 8.0.", category=DeprecationWarning)
|
| -
|
| -
|
| - def parseOptions(self, options=None):
|
| - if options is None:
|
| - options = sys.argv[1:] or ["--help"]
|
| - usage.Options.parseOptions(self, options)
|
| -
|
| - def postOptions(self):
|
| - if self.subCommand or self['python']:
|
| - self['no_save'] = True
|
| -
|
| - def subCommands(self):
|
| - from twisted import plugin
|
| - plugins = plugin.getPlugins(service.IServiceMaker)
|
| - self.loadedPlugins = {}
|
| - for plug in plugins:
|
| - self.loadedPlugins[plug.tapname] = plug
|
| - yield (plug.tapname, None, lambda: plug.options(), plug.description)
|
| - subCommands = property(subCommands)
|
| -
|
| -
|
| -
|
| -def run(runApp, ServerOptions):
|
| - config = ServerOptions()
|
| - try:
|
| - config.parseOptions()
|
| - except usage.error, ue:
|
| - print config
|
| - print "%s: %s" % (sys.argv[0], ue)
|
| - else:
|
| - runApp(config)
|
| -
|
| -
|
| -def initialLog():
|
| - from twisted.internet import reactor
|
| - log.msg("twistd %s (%s %s) starting up" % (copyright.version,
|
| - sys.executable,
|
| - runtime.shortPythonVersion()))
|
| - log.msg('reactor class: %s' % reactor.__class__)
|
| -
|
| -
|
| -def convertStyle(filein, typein, passphrase, fileout, typeout, encrypt):
|
| - application = service.loadApplication(filein, typein, passphrase)
|
| - sob.IPersistable(application).setStyle(typeout)
|
| - passphrase = getSavePassphrase(encrypt)
|
| - if passphrase:
|
| - fileout = None
|
| - sob.IPersistable(application).save(filename=fileout, passphrase=passphrase)
|
| -
|
| -def startApplication(application, save):
|
| - from twisted.internet import reactor
|
| - service.IService(application).startService()
|
| - if save:
|
| - p = sob.IPersistable(application)
|
| - reactor.addSystemEventTrigger('after', 'shutdown', p.save, 'shutdown')
|
| - reactor.addSystemEventTrigger('before', 'shutdown',
|
| - service.IService(application).stopService)
|
| -
|
| -def getLogFile(logfilename):
|
| - """
|
| - Build a log file from the full path.
|
| - """
|
| - import warnings
|
| - warnings.warn(
|
| - "app.getLogFile is deprecated. Use "
|
| - "twisted.python.logfile.LogFile.fromFullPath instead",
|
| - DeprecationWarning, stacklevel=2)
|
| -
|
| - return logfile.LogFile.fromFullPath(logfilename)
|
| -
|
|
|