Skip to content

Commit

Permalink
Merge pull request #110 from zopefoundation/issue104
Browse files Browse the repository at this point in the history
Rename all 'async' to 'async_' for compatibility with Python 3.7.
  • Loading branch information
jimfulton committed Mar 28, 2018
2 parents 5d50e0c + 6939438 commit b823ccd
Show file tree
Hide file tree
Showing 18 changed files with 79 additions and 59 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Expand Up @@ -13,10 +13,10 @@ matrix:
- os: linux
python: 3.6
- os: linux
python: 3.4
python: 3.6
env: ZEO_MTACCEPTOR=1
- os: linux
python: 3.5
python: 3.6
env: ZEO_MSGPACK=1 ZEO_MTACCEPTOR=1
- os: linux
python: 2.7
Expand Down
9 changes: 8 additions & 1 deletion CHANGES.rst
Expand Up @@ -12,6 +12,14 @@ Changelog
aren't supported on Windows. See `issue 107
<https://github.com/zopefoundation/ZEO/issues/107>`_.

- Renamed all ``async`` attributes to ``async_`` for compatibility
with Python 3.7. See `issue 104
<https://github.com/zopefoundation/ZEO/issues/104>`_.

- Fix: Client-side updates for ZODB 5.4.0 or databases that already
had ``zodbpickle.binary`` OIDs. See `issue 113
<https://github.com/zopefoundation/ZEO/issues/113>`_.

5.1.2 (2018-03-27)
------------------

Expand All @@ -21,7 +29,6 @@ Changelog
necessary for compatibility with ZODB 5.4.0 on Python 2. See `issue
107 <https://github.com/zopefoundation/ZEO/issues/107>`_.)


5.1.1 (2017-12-18)
------------------

Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -33,6 +33,7 @@
'random2',
'mock',
'msgpack-python',
'zope.testrunner',
]

classifiers = """
Expand Down
2 changes: 1 addition & 1 deletion src/ZEO/ClientStorage.py
Expand Up @@ -271,7 +271,7 @@ def __init__(self, addr, storage='1', cache_size=20 * MB,
credentials=credentials,
)
self._call = self._server.call
self._async = self._server.async
self._async = self._server.async_
self._async_iter = self._server.async_iter
self._wait = self._server.wait

Expand Down
4 changes: 2 additions & 2 deletions src/ZEO/StorageServer.py
Expand Up @@ -104,7 +104,7 @@ def notify_connected(self, conn):
self.connected = True
assert conn.protocol_version is not None
self.log_label = _addr_label(conn.addr)
self.async = conn.async
self.async_ = conn.async_
self.async_threadsafe = conn.async_threadsafe

def notify_disconnected(self):
Expand Down Expand Up @@ -337,7 +337,7 @@ def tpc_finish(self, id):

self.stats.commits += 1
self.storage.tpc_finish(self.transaction, self._invalidate)
self.async('info', self.get_size_info())
self.async_('info', self.get_size_info())
# Note that the tid is still current because we still hold the
# commit lock. We'll relinquish it in _clear_transaction.
tid = self.storage.lastTransaction()
Expand Down
8 changes: 4 additions & 4 deletions src/ZEO/asyncio/client.py
Expand Up @@ -203,10 +203,10 @@ def finish_connect(self, protocol_version):

exception_type_type = type(Exception)
def message_received(self, data):
msgid, async, name, args = self.decode(data)
msgid, async_, name, args = self.decode(data)
if name == '.reply':
future = self.futures.pop(msgid)
if (async): # ZEO 5 exception
if async_: # ZEO 5 exception
class_, args = args
factory = exc_factories.get(class_)
if factory:
Expand All @@ -231,7 +231,7 @@ def message_received(self, data):
else:
future.set_result(args)
else:
assert async # clients only get async calls
assert async_ # clients only get async calls
if name in self.client_methods:
getattr(self.client, name)(*args)
else:
Expand Down Expand Up @@ -770,7 +770,7 @@ def call_future(self, method, *args):
self.call_threadsafe, result, True, method, args)
return result

def async(self, method, *args):
def async_(self, method, *args):
return self.__call(self.call_async_threadsafe, method, args)

def async_iter(self, it):
Expand Down
7 changes: 5 additions & 2 deletions src/ZEO/asyncio/marshal.py
Expand Up @@ -24,6 +24,7 @@
from .._compat import Unpickler, Pickler, BytesIO, PY3, PYPY
from ..shortrepr import short_repr

PY2 = not PY3
logger = logging.getLogger(__name__)

def encoder(protocol, server=False):
Expand Down Expand Up @@ -132,6 +133,8 @@ def reduce_exception(exc):

exception_type_type = type(Exception)

_SAFE_MODULE_NAMES = ('ZopeUndo.Prefix', 'copy_reg', '__builtin__', 'zodbpickle')

def find_global(module, name):
"""Helper for message unpickler"""
try:
Expand All @@ -144,7 +147,7 @@ def find_global(module, name):
except AttributeError:
raise ImportError("module %s has no global %s" % (module, name))

safe = getattr(r, '__no_side_effects__', 0)
safe = getattr(r, '__no_side_effects__', 0) or (PY2 and module in _SAFE_MODULE_NAMES)
if safe:
return r

Expand All @@ -156,7 +159,7 @@ def find_global(module, name):

def server_find_global(module, name):
"""Helper for message unpickler"""
if module not in ('ZopeUndo.Prefix', 'copy_reg', '__builtin__', 'zodbpickle'):
if module not in _SAFE_MODULE_NAMES:
raise ImportError("Module not allowed: %s" % (module,))

try:
Expand Down
10 changes: 5 additions & 5 deletions src/ZEO/asyncio/server.py
Expand Up @@ -86,7 +86,7 @@ def call_soon_threadsafe(self, func, *args):

def message_received(self, message):
try:
message_id, async, name, args = self.decode(message)
message_id, async_, name, args = self.decode(message)
except Exception:
logger.exception("Can't deserialize message")
self.close()
Expand All @@ -104,13 +104,13 @@ def message_received(self, message):
except Exception as exc:
if not isinstance(exc, self.unlogged_exception_types):
logger.exception(
"Bad %srequest, %r", 'async ' if async else '', name)
if async:
"Bad %srequest, %r", 'async ' if async_ else '', name)
if async_:
return self.close() # No way to recover/cry for help
else:
return self.send_error(message_id, exc)

if not async:
if not async_:
self.send_reply(message_id, result)

def send_reply(self, message_id, result, send_error=False, flag=0):
Expand Down Expand Up @@ -138,7 +138,7 @@ def send_error(self, message_id, exc, send_error=False):
"""
self.send_reply(message_id, reduce_exception(exc), send_error, 2)

def async(self, method, *args):
def async_(self, method, *args):
self.call_async(method, args)

def async_threadsafe(self, method, *args):
Expand Down
5 changes: 4 additions & 1 deletion src/ZEO/asyncio/testing.py
Expand Up @@ -167,7 +167,10 @@ def start(self, wait=True):
def call(self, method, *args, **kw):
return getattr(self, method)(*args)

async = async_iter = call
async_ = async_iter = call

def wait(self, timeout=None):
pass

def close(self):
pass
16 changes: 8 additions & 8 deletions src/ZEO/asyncio/tests.py
Expand Up @@ -112,9 +112,9 @@ def start(self,

return (wrapper, cache, self.loop, self.client, protocol, transport)

def respond(self, message_id, result, async=False):
def respond(self, message_id, result, async_=False):
self.loop.protocol.data_received(
sized(self.encode(message_id, async, '.reply', result)))
sized(self.encode(message_id, async_, '.reply', result)))

def wait_for_result(self, future, timeout):
if future.done() and future.exception() is not None:
Expand Down Expand Up @@ -160,7 +160,7 @@ def testClientBasics(self):
self.assertFalse(f1.done())

# If we try to make an async call, we get an immediate error:
self.assertRaises(ClientDisconnected, self.async, 'bar', 3, 4)
self.assertRaises(ClientDisconnected, self.async_, 'bar', 3, 4)

# The wrapper object (ClientStorage) hasn't been notified:
self.assertFalse(wrapper.notify_connected.called)
Expand Down Expand Up @@ -191,7 +191,7 @@ def testClientBasics(self):
self.assertEqual(f1.result(), 42)

# Now we can make async calls:
f2 = self.async('bar', 3, 4)
f2 = self.async_('bar', 3, 4)
self.assertTrue(f2.done() and f2.exception() is None)
self.assertEqual(self.pop(), (0, True, 'bar', (3, 4)))

Expand Down Expand Up @@ -581,10 +581,10 @@ def test_flow_control(self):

# Give the transport a small capacity:
transport.capacity = 2
self.async('foo')
self.async('bar')
self.async('baz')
self.async('splat')
self.async_('foo')
self.async_('bar')
self.async_('baz')
self.async_('splat')

# The first 2 were sent, but the remaining were queued.
self.assertEqual(self.pop(),
Expand Down
13 changes: 7 additions & 6 deletions src/ZEO/tests/ConnectionTests.py
Expand Up @@ -965,13 +965,14 @@ def checkTimeout(self):
self.assertRaises(ClientDisconnected, storage.tpc_finish, txn)

# Make sure it's logged as CRITICAL
for line in open("server.log"):
if (('Transaction timeout after' in line) and
('CRITICAL ZEO.StorageServer' in line)
with open("server.log") as f:
for line in f:
if (('Transaction timeout after' in line) and
('CRITICAL ZEO.StorageServer' in line)
):
break
else:
self.assertTrue(False, 'bad logging')
break
else:
self.fail('bad logging')

storage.close()

Expand Down
22 changes: 11 additions & 11 deletions src/ZEO/tests/ZEO4/zrpc/connection.py
Expand Up @@ -418,10 +418,10 @@ def message_input(self, message):
# will raise an exception. The exception will ultimately
# result in asycnore calling handle_error(), which will
# close the connection.
msgid, async, name, args = self.decode(message)
msgid, async_, name, args = self.decode(message)

if debug_zrpc:
self.log("recv msg: %s, %s, %s, %s" % (msgid, async, name,
self.log("recv msg: %s, %s, %s, %s" % (msgid, async_, name,
short_repr(args)),
level=TRACE)

Expand All @@ -446,12 +446,12 @@ def message_input(self, message):
self.send_reply(msgid, ret)

elif name == REPLY:
assert not async
assert not async_
self.handle_reply(msgid, args)
else:
self.handle_request(msgid, async, name, args)
self.handle_request(msgid, async_, name, args)

def handle_request(self, msgid, async, name, args):
def handle_request(self, msgid, async_, name, args):
obj = self.obj

if name.startswith('_') or not hasattr(obj, name):
Expand Down Expand Up @@ -482,14 +482,14 @@ def handle_request(self, msgid, async, name, args):
self.log("%s() raised exception: %s" % (name, msg),
logging.ERROR, exc_info=True)
error = sys.exc_info()[:2]
if async:
if async_:
self.log("Asynchronous call raised exception: %s" % self,
level=logging.ERROR, exc_info=True)
else:
self.return_error(msgid, *error)
return

if async:
if async_:
if ret is not None:
raise ZRPCError("async method %s returned value %s" %
(name, short_repr(ret)))
Expand Down Expand Up @@ -543,17 +543,17 @@ def setSessionKey(self, key):
else:
self.__super_setSessionKey(key)

def send_call(self, method, args, async=False):
def send_call(self, method, args, async_=False):
# send a message and return its msgid
if async:
if async_:
msgid = 0
else:
msgid = self._new_msgid()

if debug_zrpc:
self.log("send msg: %d, %d, %s, ..." % (msgid, async, method),
self.log("send msg: %d, %d, %s, ..." % (msgid, async_, method),
level=TRACE)
buf = self.encode(msgid, async, method, args)
buf = self.encode(msgid, async_, method, args)
self.message_output(buf)
return msgid

Expand Down
11 changes: 8 additions & 3 deletions src/ZEO/tests/ZEO4/zrpc/marshal.py
Expand Up @@ -17,6 +17,8 @@
from .error import ZRPCError
from .log import log, short_repr

PY2 = not PY3

def encode(*args): # args: (msgid, flags, name, args)
# (We used to have a global pickler, but that's not thread-safe. :-( )

Expand Down Expand Up @@ -106,6 +108,8 @@ def server_decode(msg):

exception_type_type = type(Exception)

_SAFE_MODULE_NAMES = ('ZopeUndo.Prefix', 'copy_reg', '__builtin__', 'zodbpickle')

def find_global(module, name):
"""Helper for message unpickler"""
try:
Expand All @@ -118,7 +122,7 @@ def find_global(module, name):
except AttributeError:
raise ZRPCError("module %s has no global %s" % (module, name))

safe = getattr(r, '__no_side_effects__', 0)
safe = getattr(r, '__no_side_effects__', 0) or (PY2 and module in _SAFE_MODULE_NAMES)
if safe:
return r

Expand All @@ -130,9 +134,10 @@ def find_global(module, name):

def server_find_global(module, name):
"""Helper for message unpickler"""
if module not in _SAFE_MODULE_NAMES:
raise ImportError("Module not allowed: %s" % (module,))

try:
if module != 'ZopeUndo.Prefix':
raise ImportError
m = __import__(module, _globals, _globals, _silly)
except ImportError as msg:
raise ZRPCError("import error %s: %s" % (module, msg))
Expand Down
4 changes: 1 addition & 3 deletions src/ZEO/tests/testConversionSupport.py
Expand Up @@ -60,7 +60,7 @@ class FakeConnection(object):
addr = 'test'

call_soon_threadsafe = lambda f, *a: f(*a)
async = async_threadsafe = None
async_ = async_threadsafe = None

def test_server_record_iternext():
"""
Expand Down Expand Up @@ -123,8 +123,6 @@ def test_client_record_iternext():
...
... return oid, oid*8, 'data ' + oid, next
...
... def close(self):
... pass
>>> client = ZEO.client(
... '', wait=False, _client_factory=Client)
Expand Down
1 change: 1 addition & 0 deletions src/ZEO/tests/testTransactionBuffer.py
Expand Up @@ -40,6 +40,7 @@ def checkTypicalUsage(self):
store(tbuf)
for o in tbuf:
pass
tbuf.close()

def checkOrderPreserved(self):
tbuf = TransactionBuffer(0)
Expand Down

0 comments on commit b823ccd

Please sign in to comment.