_twist.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. from twisted.application.app import _exitWithSignal
  14. from twisted.internet.interfaces import _ISupportsExitSignalCapturing
  15. class Twist(object):
  16. """
  17. Run a Twisted application.
  18. """
  19. @staticmethod
  20. def options(argv):
  21. """
  22. Parse command line options.
  23. @param argv: Command line arguments.
  24. @type argv: L{list}
  25. @return: The parsed options.
  26. @rtype: L{TwistOptions}
  27. """
  28. options = TwistOptions()
  29. try:
  30. options.parseOptions(argv[1:])
  31. except UsageError as e:
  32. exit(ExitStatus.EX_USAGE, "Error: {}\n\n{}".format(e, options))
  33. return options
  34. @staticmethod
  35. def service(plugin, options):
  36. """
  37. Create the application service.
  38. @param plugin: The name of the plugin that implements the service
  39. application to run.
  40. @type plugin: L{str}
  41. @param options: Options to pass to the application.
  42. @type options: L{twisted.python.usage.Options}
  43. @return: The created application service.
  44. @rtype: L{IService}
  45. """
  46. service = plugin.makeService(options)
  47. application = Application(plugin.tapname)
  48. service.setServiceParent(application)
  49. return IService(application)
  50. @staticmethod
  51. def startService(reactor, service):
  52. """
  53. Start the application service.
  54. @param reactor: The reactor to run the service with.
  55. @type reactor: L{twisted.internet.interfaces.IReactorCore}
  56. @param service: The application service to run.
  57. @type service: L{IService}
  58. """
  59. service.startService()
  60. # Ask the reactor to stop the service before shutting down
  61. reactor.addSystemEventTrigger(
  62. "before", "shutdown", service.stopService
  63. )
  64. @staticmethod
  65. def run(twistOptions):
  66. """
  67. Run the application service.
  68. @param twistOptions: Command line options to convert to runner
  69. arguments.
  70. @type twistOptions: L{TwistOptions}
  71. """
  72. runner = Runner(
  73. reactor=twistOptions["reactor"],
  74. defaultLogLevel=twistOptions["logLevel"],
  75. logFile=twistOptions["logFile"],
  76. fileLogObserverFactory=twistOptions["fileLogObserverFactory"],
  77. )
  78. runner.run()
  79. reactor = twistOptions["reactor"]
  80. if _ISupportsExitSignalCapturing.providedBy(reactor):
  81. if reactor._exitSignal is not None:
  82. _exitWithSignal(reactor._exitSignal)
  83. @classmethod
  84. def main(cls, argv=sys.argv):
  85. """
  86. Executable entry point for L{Twist}.
  87. Processes options and run a twisted reactor with a service.
  88. @param argv: Command line arguments.
  89. @type argv: L{list}
  90. """
  91. options = cls.options(argv)
  92. reactor = options["reactor"]
  93. service = cls.service(
  94. plugin=options.plugins[options.subCommand],
  95. options=options.subOptions,
  96. )
  97. cls.startService(reactor, service)
  98. cls.run(options)