_twist.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # -*- test-case-name: twisted.application.twist.test.test_twist -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Run a Twisted application.
  6. """
  7. import sys
  8. from twisted.python.usage import UsageError
  9. from ..service import Application, IService
  10. from ..runner._exit import exit, ExitStatus
  11. from ..runner._runner import Runner
  12. from ._options import TwistOptions
  13. class Twist(object):
  14. """
  15. Run a Twisted application.
  16. """
  17. @staticmethod
  18. def options(argv):
  19. """
  20. Parse command line options.
  21. @param argv: Command line arguments.
  22. @type argv: L{list}
  23. @return: The parsed options.
  24. @rtype: L{TwistOptions}
  25. """
  26. options = TwistOptions()
  27. try:
  28. options.parseOptions(argv[1:])
  29. except UsageError as e:
  30. exit(ExitStatus.EX_USAGE, "Error: {}\n\n{}".format(e, options))
  31. return options
  32. @staticmethod
  33. def service(plugin, options):
  34. """
  35. Create the application service.
  36. @param plugin: The name of the plugin that implements the service
  37. application to run.
  38. @type plugin: L{str}
  39. @param options: Options to pass to the application.
  40. @type options: L{twisted.python.usage.Options}
  41. @return: The created application service.
  42. @rtype: L{IService}
  43. """
  44. service = plugin.makeService(options)
  45. application = Application(plugin.tapname)
  46. service.setServiceParent(application)
  47. return IService(application)
  48. @staticmethod
  49. def startService(reactor, service):
  50. """
  51. Start the application service.
  52. @param reactor: The reactor to run the service with.
  53. @type reactor: L{twisted.internet.interfaces.IReactorCore}
  54. @param service: The application service to run.
  55. @type service: L{IService}
  56. """
  57. service.startService()
  58. # Ask the reactor to stop the service before shutting down
  59. reactor.addSystemEventTrigger(
  60. "before", "shutdown", service.stopService
  61. )
  62. @staticmethod
  63. def runnerArguments(twistOptions):
  64. """
  65. Take options obtained from command line and configure arguments to pass
  66. to the application runner.
  67. @param twistOptions: Command line options to convert to runner
  68. arguments.
  69. @type twistOptions: L{TwistOptions}
  70. @return: The corresponding runner arguments.
  71. @rtype: L{dict}
  72. """
  73. return dict(
  74. reactor=twistOptions["reactor"],
  75. defaultLogLevel=twistOptions["logLevel"],
  76. logFile=twistOptions["logFile"],
  77. fileLogObserverFactory=twistOptions["fileLogObserverFactory"],
  78. )
  79. @staticmethod
  80. def run(runnerArguments):
  81. """
  82. Run the application service.
  83. @param runnerArguments: Arguments to pass to the runner.
  84. @type runnerArguments: L{dict}
  85. """
  86. runner = Runner(**runnerArguments)
  87. runner.run()
  88. @classmethod
  89. def main(cls, argv=sys.argv):
  90. """
  91. Executable entry point for L{Twist}.
  92. Processes options and run a twisted reactor with a service.
  93. @param argv: Command line arguments.
  94. @type argv: L{list}
  95. """
  96. options = cls.options(argv)
  97. reactor = options["reactor"]
  98. service = cls.service(
  99. plugin=options.plugins[options.subCommand],
  100. options=options.subOptions,
  101. )
  102. cls.startService(reactor, service)
  103. cls.run(cls.runnerArguments(options))