Beispiel #1
0
    def __init__(self, module, cls, init_args, *, interpreter=sys.executable):
        """Create a subprocess and the object specified by the arguments in it.

        The object can then be interacted remotely with by using call_method.

        Remote debugging is also enabled for the process so that
        breakpoints trigger a remote debugger.
        """
        env = os.environ.copy()
        env.update(dict(REMOTE_PDB='1', PYTHONBREAKPOINT='rpdb.set_trace'))
        self.proc = subprocess.Popen(
            [interpreter, '-m', 'myia.compile.channel'],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            bufsize=0,
            env=env)
        self.dumper = MyiaDumper(self.proc.stdin.fileno())
        self.loader = MyiaLoader(self.proc.stdout.fileno())
        self.dumper.open()
        self.dumper.represent((module, cls, init_args))
        try:
            resp = self._read_msg()
        except Exception:
            os.waitpid(-1, 0)
            raise
        assert resp == 'ready'
Beispiel #2
0
class RPCProcess:
    """Object that represents a remote class in another process."""

    def __init__(self, module, cls, init_args, *, interpreter=sys.executable):
        """Create a subprocess and the object specified by the arguments in it.

        The object can then be interacted remotely with by using call_method.

        Remote debugging is also enabled for the process so that
        breakpoints trigger a remote debugger.
        """
        env = os.environ.copy()
        env.update(dict(REMOTE_PDB="1", PYTHONBREAKPOINT="rpdb.set_trace"))
        self.proc = subprocess.Popen(
            [interpreter, "-m", "myia.compile.channel"],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            bufsize=0,
            env=env,
        )
        self.dumper = MyiaDumper(self.proc.stdin.fileno())
        self.loader = MyiaLoader(self.proc.stdout.fileno())
        self.dumper.open()
        self.dumper.represent((module, cls, init_args))
        try:
            resp = self._read_msg()
        except Exception:
            os.waitpid(-1, 0)
            raise
        assert resp == "ready"

    def call_method(self, name, *args, **kwargs):
        """Call a method on the remote object."""
        self.dumper.represent((name, args, kwargs))
        return self._read_msg()

    def call_handle(self, handle, args, kwargs):
        """Call the object associated with a handle."""
        self._send_msg("handle_call", (handle, args, kwargs))
        return self._read_msg()

    def _send_msg(self, msg, args):
        self.dumper.represent([msg, args])

    def _read_msg(self):
        RemoteHandle.current_channel = self
        try:
            res = self.loader.get_data()
        finally:
            RemoteHandle.current_channel = None
        if isinstance(res, LoadedError):
            raise res
        return res
Beispiel #3
0
def _rpc_server():
    # Try to prevent other libs from using stdout
    sys.stdout = sys.stderr
    dumper = MyiaDumper(1)
    dumper.open()
    loader = MyiaLoader(0)
    pkg, name, init_args = loader.get_data()
    try:
        mod = importlib.import_module(pkg)
        cls = getattr(mod, name)
        iface = cls(**init_args)
        dumper.represent('ready')
    except Exception as e:
        dumper.represent(e)
        return 1

    while loader.check_data():
        data = loader.get_data()
        if isinstance(data, tuple):
            name, args, kwargs = data
            try:
                meth = getattr(iface, name)
                res = meth(*args, **kwargs)
            except Exception as e:
                res = e
            dumper.represent(res)
        elif isinstance(data, list):
            msg, arg = data
            if msg == 'dead_handle':
                _dead_handle(arg)
            elif msg == 'handle_call':
                try:
                    res = arg[0](*arg[1], **arg[2])
                except Exception as e:  # pragma: no cover
                    res = e
                dumper.represent(res)
            else:
                raise ValueError(f"Unknown message: {msg}")  # pragma: no cover
        else:  # pragma: no cover
            raise TypeError(f"bad data {data}")
    return 0
Beispiel #4
0
def _rpc_server():
    # Try to prevent other libs from using stdout
    sys.stdout = sys.stderr
    do_pm = os.environ.get("MYIA_PYTEST_USE_PDB", False)
    dumper = MyiaDumper(1)
    dumper.open()
    loader = MyiaLoader(0)
    pkg, name, init_args = loader.get_data()
    try:
        mod = importlib.import_module(pkg)
        cls = getattr(mod, name)
        iface = cls(**init_args)
        dumper.represent("ready")
    except Exception as e:
        if do_pm:  # pragma: no cover
            import rpdb

            rpdb.post_mortem()
        dumper.represent(e)
        return 1

    while loader.check_data():
        data = loader.get_data()
        if isinstance(data, tuple):
            name, args, kwargs = data
            try:
                meth = getattr(iface, name)
                res = meth(*args, **kwargs)
            except Exception as e:  # pragma: no cover
                if do_pm:  # pragma: no cover
                    import rpdb

                    rpdb.post_mortem()
                res = e
            dumper.represent(res)
        elif isinstance(data, list):
            msg, arg = data
            if msg == "dead_handle":
                _dead_handle(arg)
            elif msg == "handle_call":
                try:
                    res = arg[0](*arg[1], **arg[2])
                except Exception as e:  # pragma: no cover
                    if do_pm:  # pragma: no cover
                        import rpdb

                        rpdb.post_mortem()
                    res = e
                dumper.represent(res)
            else:
                raise ValueError(f"Unknown message: {msg}")  # pragma: no cover
        else:  # pragma: no cover
            raise TypeError(f"bad data {data}")
    return 0