workertrial.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # -*- test-case-name: twisted.trial._dist.test.test_workertrial -*-
  2. #
  3. # Copyright (c) Twisted Matrix Laboratories.
  4. # See LICENSE for details.
  5. """
  6. Implementation of C{AMP} worker commands, and main executable entry point for
  7. the workers.
  8. @since: 12.3
  9. """
  10. import sys
  11. import os
  12. import errno
  13. def _setupPath(environ):
  14. """
  15. Override C{sys.path} with what the parent passed in B{TRIAL_PYTHONPATH}.
  16. @see: twisted.trial._dist.disttrial.DistTrialRunner.launchWorkerProcesses
  17. """
  18. if 'TRIAL_PYTHONPATH' in environ:
  19. sys.path[:] = environ['TRIAL_PYTHONPATH'].split(os.pathsep)
  20. _setupPath(os.environ)
  21. from twisted.internet.protocol import FileWrapper
  22. from twisted.python.log import startLoggingWithObserver, textFromEventDict
  23. from twisted.trial._dist.options import WorkerOptions
  24. from twisted.trial._dist import _WORKER_AMP_STDIN, _WORKER_AMP_STDOUT
  25. class WorkerLogObserver(object):
  26. """
  27. A log observer that forward its output to a C{AMP} protocol.
  28. """
  29. def __init__(self, protocol):
  30. """
  31. @param protocol: a connected C{AMP} protocol instance.
  32. @type protocol: C{AMP}
  33. """
  34. self.protocol = protocol
  35. def emit(self, eventDict):
  36. """
  37. Produce a log output.
  38. """
  39. from twisted.trial._dist import managercommands
  40. text = textFromEventDict(eventDict)
  41. if text is None:
  42. return
  43. self.protocol.callRemote(managercommands.TestWrite, out=text)
  44. def main(_fdopen=os.fdopen):
  45. """
  46. Main function to be run if __name__ == "__main__".
  47. @param _fdopen: If specified, the function to use in place of C{os.fdopen}.
  48. @param _fdopen: C{callable}
  49. """
  50. config = WorkerOptions()
  51. config.parseOptions()
  52. from twisted.trial._dist.worker import WorkerProtocol
  53. workerProtocol = WorkerProtocol(config['force-gc'])
  54. protocolIn = _fdopen(_WORKER_AMP_STDIN, 'rb')
  55. protocolOut = _fdopen(_WORKER_AMP_STDOUT, 'wb')
  56. workerProtocol.makeConnection(FileWrapper(protocolOut))
  57. observer = WorkerLogObserver(workerProtocol)
  58. startLoggingWithObserver(observer.emit, False)
  59. while True:
  60. try:
  61. r = protocolIn.read(1)
  62. except IOError as e:
  63. if e.args[0] == errno.EINTR:
  64. if sys.version_info < (3, 0):
  65. sys.exc_clear()
  66. continue
  67. else:
  68. raise
  69. if r == b'':
  70. break
  71. else:
  72. workerProtocol.dataReceived(r)
  73. protocolOut.flush()
  74. sys.stdout.flush()
  75. sys.stderr.flush()
  76. if config.tracer:
  77. sys.settrace(None)
  78. results = config.tracer.results()
  79. results.write_results(show_missing=True, summary=False,
  80. coverdir=config.coverdir().path)
  81. if __name__ == '__main__':
  82. main()