Skip to content

Commit

Permalink
fixes: closes #61; closes #62; closes #63
Browse files Browse the repository at this point in the history
  • Loading branch information
tomerfiliba committed Feb 27, 2012
1 parent 1036a02 commit 725c758
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 33 deletions.
25 changes: 25 additions & 0 deletions issues/issue63_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import rpyc
import time

count = 0

def callbackFunc(x):
global count
count += 1
print x, time.time()

if __name__ == "__main__":
conn = rpyc.connect("localhost", 12000)
#rpyc.BgServingThread.SERVE_INTERVAL = 0.01
rpyc.BgServingThread.SLEEP_INTERVAL = 0.0001
bgsrv = rpyc.BgServingThread(conn)

test = conn.root.RemoteCallbackTest(callbackFunc)
print test
test.start()
print "doing other things while the callback is being called"
while count < 100:
time.sleep(0.1)
print "done"


27 changes: 27 additions & 0 deletions issues/issue63_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import threading
import rpyc


def run_something(callback):
for i in range(100):
callback(i)

class MyService(rpyc.Service):
def on_connect(self):
print "hi", self._conn._config["endpoints"][1]
def on_disconnect(self):
print "bye", self._conn._config["endpoints"][1]

class exposed_RemoteCallbackTest(object):
def __init__(self, callback):
self.callback = callback
def start(self):
thd = threading.Thread(target = run_something, args = (self.callback,))
thd.start()


if __name__ == "__main__":
from rpyc.utils.server import ThreadedServer
myServerObj = ThreadedServer(MyService, port=12000, protocol_config={"allow_public_attrs":True})
myServerObj.start()

10 changes: 6 additions & 4 deletions rpyc/core/brine.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,11 @@ def load(data):
return _load(stream)

if is_py3k:
simple_types = frozenset([type(None), int, bool, float, bytes, str,
slice, complex, type(NotImplemented), type(Ellipsis)])
simple_types = frozenset([type(None), int, bool, float, bytes, str, complex,
type(NotImplemented), type(Ellipsis)])
else:
simple_types = frozenset([type(None), int, long, bool, float, str, unicode,
slice, complex, type(NotImplemented), type(Ellipsis)])
simple_types = frozenset([type(None), int, long, bool, float, str, unicode, complex,
type(NotImplemented), type(Ellipsis)])

def dumpable(obj):
"""Indicates whether the given object is *dumpable* by brine
Expand All @@ -364,6 +364,8 @@ def dumpable(obj):
return True
if type(obj) in (tuple, frozenset):
return all(dumpable(item) for item in obj)
if type(obj) is slice:
return dumpable(obj.start) and dumpable(obj.stop) and dumpable(obj.step)
return False


Expand Down
13 changes: 7 additions & 6 deletions rpyc/core/netref.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ def syncreq(proxy, handler, *args):
:raises: any exception raised by the operation will be raised
:returns: the result of the operation
"""
conn = object.__getattribute__(proxy, "____conn__")
conn = object.__getattribute__(proxy, "____conn__")()
if not conn:
raise ReferenceError('weakly-referenced object no longer exists')
oid = object.__getattribute__(proxy, "____oid__")
return conn().sync_request(handler, oid, *args)
return conn.sync_request(handler, oid, *args)

def asyncreq(proxy, handler, *args):
"""Performs an asynchronous request on the given proxy object.
Expand All @@ -80,12 +82,11 @@ def asyncreq(proxy, handler, *args):
:returns: an :class:`AsyncResult <rpyc.core.async.AsyncResult>` representing
the operation
"""
conn = object.__getattribute__(proxy, "____conn__")
connection = conn()
if not connection:
conn = object.__getattribute__(proxy, "____conn__")()
if not conn:
raise ReferenceError('weakly-referenced object no longer exists')
oid = object.__getattribute__(proxy, "____oid__")
return connection.async_request(handler, oid, *args)
return conn.async_request(handler, oid, *args)

class NetrefMetaclass(type):
"""A *metaclass* used to customize the ``__repr__`` of ``netref`` classes.
Expand Down
14 changes: 11 additions & 3 deletions rpyc/core/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class PingError(Exception):
allow_pickle = False,
connid = None,
credentials = None,
endpoints = None,
)
"""
The default configuration dictionary of the protocol. You can override these parameters
Expand All @@ -64,7 +65,7 @@ class PingError(Exception):
to repeat parameters whose values remain unchanged.
===================================== ================ =====================================================
Parameter Default value Description
Parameter Default value Description
===================================== ================ =====================================================
``allow_safe_attrs`` ``True`` Whether to allow the use of *safe* attributes
(only those listed as ``safe_attrs``)
Expand All @@ -87,15 +88,22 @@ class PingError(Exception):
``import_custom_exceptions`` ``False`` Whether to allow importing of
exceptions from not-yet-imported modules
``instantiate_oldstyle_exceptions`` ``False`` Whether to allow instantiation of exceptions
which don't derive from ``Exception``
which don't derive from ``Exception``. This
is not applicable for Python 3 and later.
``propagate_SystemExit_locally`` ``False`` Whether to propagate ``SystemExit``
locally or to the other party
locally (kill the server) or to the other
party (kill the client)
``connid`` ``None`` **Runtime**: the RPyC connection ID (used
mainly for debugging purposes)
``credentials`` ``None`` **Runtime**: the credentails object that was returned
by the server's :ref:`authenticator <api-authenticators>`
or ``None``
``endpoints`` ``None`` **Runtime**: The connection's endpoints. This is a tuple
made of the local socket endpoint (``getsockname``) and the
remote one (``getpeername``). This is set by the server
upon accepting a connection; client side connections
do no have this configuration option set.
===================================== ================ =====================================================
"""

Expand Down
37 changes: 18 additions & 19 deletions rpyc/core/vinegar.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,18 @@ class simply doesn't exist on the local machine), a :class:`GenericException`
details.
:param val: the dumped exception
:param import_custom_exceptions: whether to allow this function to import
custom modules (imposes a security risk)
:param instantiate_custom_exceptions: whether to allow this function to
instantiate "custom exceptions" (i.e.,
not one of the built-in exceptions,
:param import_custom_exceptions: whether to allow this function to import custom modules
(imposes a security risk)
:param instantiate_custom_exceptions: whether to allow this function to instantiate "custom
exceptions" (i.e., not one of the built-in exceptions,
such as ``ValueError``, ``OSError``, etc.)
:param instantiate_oldstyle_exceptions: whether to allow this function to
instantiate exception classes that
do not derive from ``BaseException``.
This is required to support old-style
exceptions.
:param instantiate_oldstyle_exceptions: whether to allow this function to instantiate exception
classes that do not derive from ``BaseException``.
This is required to support old-style exceptions.
Not applicable for Python 3 and above.
:returns: A throwable exception object
"""

if val == consts.EXC_STOP_ITERATION:
return StopIteration # optimization
if type(val) is str:
Expand All @@ -121,21 +118,23 @@ class simply doesn't exist on the local machine), a :class:`GenericException`
if instantiate_custom_exceptions:
if modname in sys.modules:
cls = getattr(sys.modules[modname], clsname, None)
elif not is_py3k and modname == "builtins":
cls = getattr(exceptions_module, clsname, None)
else:
cls = None
elif modname == exceptions_module.__name__:
cls = getattr(exceptions_module, clsname, None)
else:
cls = None

if not isinstance(cls, (type, ClassType)):
cls = None
elif issubclass(cls, ClassType) and not instantiate_oldstyle_exceptions:
cls = None
elif not issubclass(cls, BaseException):
cls = None
if is_py3k:
if not isinstance(cls, type) or not issubclass(cls, BaseException):
cls = None
else:
if not isinstance(cls, (type, ClassType)):
cls = None
elif issubclass(cls, ClassType) and not instantiate_oldstyle_exceptions:
cls = None
elif not issubclass(cls, BaseException):
cls = None

if cls is None:
fullname = "%s.%s" % (modname, clsname)
Expand Down
3 changes: 2 additions & 1 deletion rpyc/utils/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ def _serve_client(self, sock, credentials):
else:
self.logger.info("welcome [%s]:%s", h, p)
try:
config = dict(self.protocol_config, credentials = credentials)
config = dict(self.protocol_config, credentials = credentials,
endpoints = (sock.getsockname(), addrinfo))
conn = Connection(self.service, Channel(SocketStream(sock)),
config = config, _lazy = True)
conn._init_service()
Expand Down

0 comments on commit 725c758

Please sign in to comment.