gateway_bootstrap.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """
  2. code to initialize the remote side of a gateway once the io is created
  3. """
  4. import os
  5. import inspect
  6. import execnet
  7. from execnet import gateway_base
  8. from execnet.gateway import Gateway
  9. importdir = os.path.dirname(os.path.dirname(execnet.__file__))
  10. class HostNotFound(Exception):
  11. pass
  12. def bootstrap_import(io, spec):
  13. # only insert the importdir into the path if we must. This prevents
  14. # bugs where backports expect to be shadowed by the standard library on
  15. # newer versions of python but would instead shadow the standard library
  16. sendexec(
  17. io,
  18. "import sys",
  19. "if %r not in sys.path:" % importdir,
  20. " sys.path.insert(0, %r)" % importdir,
  21. "from execnet.gateway_base import serve, init_popen_io, get_execmodel",
  22. "sys.stdout.write('1')",
  23. "sys.stdout.flush()",
  24. "execmodel = get_execmodel(%r)" % spec.execmodel,
  25. "serve(init_popen_io(execmodel), id='%s-slave')" % spec.id,
  26. )
  27. s = io.read(1)
  28. assert s == "1".encode('ascii'), repr(s)
  29. def bootstrap_exec(io, spec):
  30. try:
  31. sendexec(
  32. io,
  33. inspect.getsource(gateway_base),
  34. "execmodel = get_execmodel(%r)" % spec.execmodel,
  35. 'io = init_popen_io(execmodel)',
  36. "io.write('1'.encode('ascii'))",
  37. "serve(io, id='%s-slave')" % spec.id,
  38. )
  39. s = io.read(1)
  40. assert s == "1".encode('ascii')
  41. except EOFError:
  42. ret = io.wait()
  43. if ret == 255:
  44. raise HostNotFound(io.remoteaddress)
  45. def bootstrap_socket(io, id):
  46. # XXX: switch to spec
  47. from execnet.gateway_socket import SocketIO
  48. sendexec(
  49. io,
  50. inspect.getsource(gateway_base),
  51. 'import socket',
  52. inspect.getsource(SocketIO),
  53. "try: execmodel",
  54. "except NameError:",
  55. " execmodel = get_execmodel('thread')",
  56. "io = SocketIO(clientsock, execmodel)",
  57. "io.write('1'.encode('ascii'))",
  58. "serve(io, id='%s-slave')" % id,
  59. )
  60. s = io.read(1)
  61. assert s == "1".encode('ascii')
  62. def sendexec(io, *sources):
  63. source = "\n".join(sources)
  64. io.write((repr(source) + "\n").encode('ascii'))
  65. def fix_pid_for_jython_popen(gw):
  66. """
  67. fix for jython 2.5.1
  68. """
  69. spec, io = gw.spec, gw._io
  70. if spec.popen and not spec.via:
  71. # XXX: handle the case of remote being jython
  72. # and not having the popen pid
  73. if io.popen.pid is None:
  74. io.popen.pid = gw.remote_exec(
  75. "import os; channel.send(os.getpid())").receive()
  76. def bootstrap(io, spec):
  77. if spec.popen:
  78. if spec.via or spec.python:
  79. bootstrap_exec(io, spec)
  80. else:
  81. bootstrap_import(io, spec)
  82. elif spec.ssh or spec.vagrant_ssh:
  83. bootstrap_exec(io, spec)
  84. elif spec.socket:
  85. bootstrap_socket(io, spec)
  86. else:
  87. raise ValueError('unknown gateway type, cant bootstrap')
  88. gw = Gateway(io, spec)
  89. fix_pid_for_jython_popen(gw)
  90. return gw