Skip to content

Commit

Permalink
messages: Make module public
Browse files Browse the repository at this point in the history
  • Loading branch information
jodal committed May 6, 2019
1 parent f54200b commit 77ccf0f
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 24 deletions.
1 change: 1 addition & 0 deletions docs/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ Pykka API
futures
registry
exceptions
messages
logging
debug
8 changes: 8 additions & 0 deletions docs/api/messages.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
========
Messages
========

.. automodule:: pykka.messages
:members:

.. versionadded:: 2.0
16 changes: 8 additions & 8 deletions pykka/_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import threading
import uuid

from pykka import ActorDeadError, ActorRef, ActorRegistry, _messages
from pykka import ActorDeadError, ActorRef, ActorRegistry, messages


__all__ = ['Actor']
Expand Down Expand Up @@ -162,7 +162,7 @@ def stop(self):
It's equivalent to calling :meth:`ActorRef.stop` with ``block=False``.
"""
self.actor_ref.tell(_messages.ActorStop())
self.actor_ref.tell(messages._ActorStop())

def _stop(self):
"""
Expand Down Expand Up @@ -219,7 +219,7 @@ def _actor_loop(self):
while not self.actor_inbox.empty():
envelope = self.actor_inbox.get()
if envelope.reply_to is not None:
if isinstance(envelope.message, _messages.ActorStop):
if isinstance(envelope.message, messages._ActorStop):
envelope.reply_to.set(None)
else:
envelope.reply_to.set_exception(
Expand Down Expand Up @@ -291,16 +291,16 @@ def on_failure(self, exception_type, exception_value, traceback):

def _handle_receive(self, message):
"""Handles messages sent to the actor."""
message = _messages.upgrade_internal_message(message)
if isinstance(message, _messages.ActorStop):
message = messages._upgrade_internal_message(message)
if isinstance(message, messages._ActorStop):
return self._stop()
if isinstance(message, _messages.ProxyCall):
if isinstance(message, messages.ProxyCall):
callee = self._get_attribute_from_path(message.attr_path)
return callee(*message.args, **message.kwargs)
if isinstance(message, _messages.ProxyGetAttr):
if isinstance(message, messages.ProxyGetAttr):
attr = self._get_attribute_from_path(message.attr_path)
return attr
if isinstance(message, _messages.ProxySetAttr):
if isinstance(message, messages.ProxySetAttr):
parent_attr = self._get_attribute_from_path(message.attr_path[:-1])
attr_name = message.attr_path[-1]
return setattr(parent_attr, attr_name, message.value)
Expand Down
10 changes: 5 additions & 5 deletions pykka/_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging

from pykka import ActorDeadError, _compat, _messages
from pykka import ActorDeadError, _compat, messages


__all__ = ['ActorProxy']
Expand Down Expand Up @@ -228,7 +228,7 @@ def __getattr__(self, name):
)
return self._actor_proxies[attr_path]
else:
message = _messages.ProxyGetAttr(attr_path=attr_path)
message = messages.ProxyGetAttr(attr_path=attr_path)
return self.actor_ref.ask(message, block=False)

def __setattr__(self, name, value):
Expand All @@ -240,7 +240,7 @@ def __setattr__(self, name, value):
if name == 'actor_ref' or name.startswith('_'):
return super(ActorProxy, self).__setattr__(name, value)
attr_path = self._attr_path + (name,)
message = _messages.ProxySetAttr(attr_path=attr_path, value=value)
message = messages.ProxySetAttr(attr_path=attr_path, value=value)
return self.actor_ref.ask(message)


Expand Down Expand Up @@ -275,7 +275,7 @@ def __call__(self, *args, **kwargs):
the exception will not be reraised. Either way, the exception will
also be logged. See :ref:`logging` for details.
"""
message = _messages.ProxyCall(
message = messages.ProxyCall(
attr_path=self._attr_path, args=args, kwargs=kwargs
)
return self.actor_ref.ask(message, block=False)
Expand All @@ -291,7 +291,7 @@ def defer(self, *args, **kwargs):
.. versionadded:: 2.0
"""
message = _messages.ProxyCall(
message = messages.ProxyCall(
attr_path=self._attr_path, args=args, kwargs=kwargs
)
return self.actor_ref.tell(message)
Expand Down
4 changes: 2 additions & 2 deletions pykka/_ref.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pykka import ActorDeadError, ActorProxy
from pykka._envelope import Envelope
from pykka._messages import ActorStop
from pykka.messages import _ActorStop


__all__ = ['ActorRef']
Expand Down Expand Up @@ -135,7 +135,7 @@ def stop(self, block=True, timeout=None):
:return: :class:`pykka.Future`, or a boolean result if blocking
"""
ask_future = self.ask(ActorStop(), block=False)
ask_future = self.ask(_ActorStop(), block=False)

def _stop_result_converter(timeout):
try:
Expand Down
36 changes: 32 additions & 4 deletions pykka/_messages.py → pykka/messages.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
"""
The :mod:`pykka.messages` module contains Pykka's own actor messages.
In general, you should not need to use any of these classes. However, they have
been made part of the public API so that certain optimizations can be done
without touching Pykka's internals.
An example is to combine :meth:`~pykka.ActorRef.ask` and :class:`ProxyCall`
to call a method on an actor without having to spend any resources on creating
a proxy object::
reply = actor_ref.ask(
ProxyCall(
attr_path=['my_method'],
args=['foo'],
kwargs={'bar': 'baz'}
)
)
Another example is to use :meth:`~pykka.ActorRef.tell` instead of
:meth:`~pykka.ActorRef.ask` for the proxy method call, and thus avoid the
creation of a future for the return value if you don't need it.
It should be noted that these optimizations should only be necessary in very
special circumstances.
"""

import warnings
from collections import namedtuple


# Internal actor messages
ActorStop = namedtuple('ActorStop', [])
_ActorStop = namedtuple('ActorStop', [])

# Internal proxy messages
# Public proxy messages
# TODO Add docstrings to classes and attributes once we drop Python 2.7 support
ProxyCall = namedtuple('ProxyCall', ['attr_path', 'args', 'kwargs'])
ProxyGetAttr = namedtuple('ProxyGetAttr', ['attr_path'])
ProxySetAttr = namedtuple('ProxySetAttr', ['attr_path', 'value'])


def upgrade_internal_message(message):
def _upgrade_internal_message(message):
"""Filter that upgrades dict-based internal messages to the new format.
This is needed for a transitional period because Mopidy < 3 uses
Expand All @@ -32,7 +60,7 @@ def upgrade_internal_message(message):

command = message.get('command')
if command == 'pykka_stop':
return ActorStop()
return _ActorStop()
elif command == 'pykka_call':
return ProxyCall(
attr_path=message['attr_path'],
Expand Down
10 changes: 5 additions & 5 deletions tests/test_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

import pytest

from pykka._messages import (
ActorStop,
from pykka.messages import (
ProxyCall,
ProxyGetAttr,
ProxySetAttr,
upgrade_internal_message,
_ActorStop,
_upgrade_internal_message,
)


@pytest.mark.parametrize(
'old_format, new_format',
[
({'command': 'pykka_stop'}, ActorStop()),
({'command': 'pykka_stop'}, _ActorStop()),
(
{
'command': 'pykka_call',
Expand Down Expand Up @@ -42,7 +42,7 @@
)
def test_upgrade_internal_message(old_format, new_format):
with warnings.catch_warnings(record=True) as w:
assert upgrade_internal_message(old_format) == new_format
assert _upgrade_internal_message(old_format) == new_format

assert len(w) == 1
assert issubclass(w[0].category, DeprecationWarning)
Expand Down

0 comments on commit 77ccf0f

Please sign in to comment.