gateway_bootstrap.py 3.0 KB

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