Skip to content

Commit

Permalink
Provide proper support for Pyro5 in the guibot proxy interface
Browse files Browse the repository at this point in the history
The previously provided support wasn't complete as it needed a
compatibility layer for the exception serialization. The current
API use now is exclusive to Pyro5 and handles its own exposing
based on class hierarchy and proxified return objects.
  • Loading branch information
pevogam committed Nov 13, 2024
1 parent af64c33 commit 7557ac8
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
28 changes: 23 additions & 5 deletions guibot/guibot_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,22 @@
"""

import re
import inspect
import logging
from typing import Any

try:
import Pyro5 as pyro
except ImportError:
import Pyro4 as pyro
import Pyro5 as pyro
from Pyro5 import server

from . import errors
from .guibot import GuiBot
from .finder import Finder
from .controller import Controller


log = logging.getLogger("guibot.proxy")


def serialize_custom_error(
class_obj: type,
) -> dict[str, "str | getset_descriptor | dictproxy"]:
Expand All @@ -69,7 +72,7 @@ def register_exception_serialization() -> None:
for it with some extra setup steps and functions below.
"""
for exception in [errors.UnsupportedBackendError]:
pyro.util.SerializerBase.register_class_to_dict(
pyro.serializers.SerializerBase.register_class_to_dict(
exception, serialize_custom_error
)

Expand Down Expand Up @@ -100,7 +103,22 @@ def _proxify(self, obj: Any) -> Any:
if isinstance(obj, (int, float, bool, str)) or obj is None:
return obj
if obj not in self._pyroDaemon.objectsById.values():
log.info("Providing proxy alternative to %s", obj)
self._pyroDaemon.register(obj)
cls = type(obj)
# counter pyro access redesigning normal python inheritance
for base_cls in cls.__mro__:
if base_cls in (object, int, float, bool, str, tuple, frozenset):
# known immutable classes should be skipped
continue
if inspect.ismethoddescriptor(base_cls):
# method descriptors should be skipped
continue
try:
server.expose(base_cls)
except (TypeError, AttributeError) as error:
log.warning("Additional class exposing error: %s", error)
continue
return obj

def nearby(self, *args: tuple[type, ...], **kwargs: dict[str, type]) -> str:
Expand Down
4 changes: 2 additions & 2 deletions packaging/pip_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ vncdotool==0.12.0; sys_platform != 'win32' and platform_python_implementation !=
pyautogui==0.9.54; platform_python_implementation != "PyPy"

# optional proxy guibot interface deps
serpent==1.40
Pyro4==4.82
serpent==1.41
Pyro5==5.14

# coverage analysis to use for testing
coverage
Expand Down
4 changes: 2 additions & 2 deletions tests/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ class ProxyAPITest(TestCase):

def setUp(self) -> None:
# fake the remote objects dependency for this interface
sys.modules["Pyro4"] = mock.MagicMock()
sys.modules["Pyro5"] = mock.MagicMock()
from guibot import guibot_proxy as remote
self.interface = remote.GuiBotProxy(cv=None, dc=None)
self.interface._proxify = mock.MagicMock()

def tearDown(self) -> None:
del sys.modules["Pyro4"]
del sys.modules["Pyro5"]

@mock.patch('guibot.guibot_proxy.super')
def test_call_delegations(self, mock_super) -> None:
Expand Down

0 comments on commit 7557ac8

Please sign in to comment.