示例#1
0
    def _handle_incoming_call(self, im: GenIncomingMessage):
        # TODO: noreply, and other stop codes
        call_msg = im.message_
        if isinstance(call_msg, tuple):
            f_name = as_str(call_msg[0])
            f_args = list(call_msg[1:])
        else:
            f_name = as_str(call_msg)
            f_args = []

        if f_name not in self.gen_accepted_calls_:
            raise GenException(
                "Call to method %s is not in accepted_calls list" % f_name)

        try:
            method = getattr(self, f_name)
            LOG.debug("method=%s", method)
            result = method(*f_args)
            LOG.debug("Replying with result=%s", result)
            im.reply(local_pid=self.pid_, result=result)

        except Exception as excpt:
            # Send an error
            if self.traceback_depth_ > 0:
                excpt.traceback = traceback.format_exc(self.traceback_depth_)

            im.reply_exit(local_pid=self.pid_, reason=excpt)
示例#2
0
文件: gen.py 项目: kor-and-m/Pyrlang
def parse_gen_call(msg, node_name: str):
    """ Determine if msg is a gen:call message and create a
        :py:class:`~Pyrlang.gen.GenIncomingCall` object.

        .. note::
            Module and function parameters to ``rpc:call`` can be
            binary, ASCII strings or atoms.

        .. note::
            You do not need to import module in ``rpc:call``, it is done by Rex.

        :param node_name: Name of the current node, used to route replies back
            to the caller
        :param msg: An Erlang tuple hopefully starting with a '$gen_call'
        :return: str with error if msg wasn't a call message, otherwise
            constructs and returns a ``GenIncomingCall`` object.
    """
    # Incoming {$gen_call, {From, Ref}, {call, Mod, Fun, Args}}
    if type(msg) != tuple:  # ignore all non-tuple messages
        return "Only {tuple} messages allowed"

    # ignore tuples with non-atom 1st, ignore non-gen_call mesages
    if not isinstance(msg[0], Atom) or msg[0].text_ != '$gen_call':
        return "Only {$gen_call, _, _} messages allowed"

    (_, _sender_mref, _call_mfa_gl) = msg
    (msender, mref) = _sender_mref

    # TODO: Maybe also check first element to be an atom 'call'
    if len(_call_mfa_gl) != 5:
        return "Expecting a 5-tuple (with a 'call' atom)"

    (call, m, f, args, group_leader) = _call_mfa_gl

    return GenIncomingCall(
        mod=as_str(m),
        fun=as_str(f),
        args=args,
        group_leader=group_leader,
        sender=msender,  # pid of the sender
        ref=mref,  # reference used in response
        node_name=node_name)
示例#3
0
    def _resolve_path(self, p: List[str]) -> Callable:
        """ Imports p[0] and then follows the list p, by applying getattr()
            repeatedly. """
        if isinstance(p, str):
            p = [p]

        # First element would be the import, or a stored value reference
        first_path_element = p[0]
        if isinstance(first_path_element, tuple) \
                and first_path_element[0] == Atom("$pyrlangval"):
            # First element is {'$pyrlangval', X} - query the value
            val = self._retrieve_value(first_path_element)
        else:
            # First element is a string, import it
            val = __import__(as_str(first_path_element))

        # Follow the elements in path, and getattr deeper
        for item in p[1:]:
            val = getattr(val, as_str(item))

        return val