workertrial.py 2.9 KB

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