Commit e01e5c2f authored by Kirill Smelkov's avatar Kirill Smelkov

channels: Make them work with Python3

Python3 complains that there is no .im_func & friends of a method.
Workaround it all with compat code.
parent 02dddb97
...@@ -32,6 +32,9 @@ __all__ = ['method', 'go', 'chan', 'select', 'default', 'panic', 'gimport'] ...@@ -32,6 +32,9 @@ __all__ = ['method', 'go', 'chan', 'select', 'default', 'panic', 'gimport']
from golang._gopath import gimport # make gimport available from golang from golang._gopath import gimport # make gimport available from golang
import threading, collections, random import threading, collections, random
import six
from golang._pycompat import im_class
# TODO -> use gevent + fallback to !gevent implementation if gevent was not initialized. # TODO -> use gevent + fallback to !gevent implementation if gevent was not initialized.
# The following should automatically prefer to use gevent as golang backend: # The following should automatically prefer to use gevent as golang backend:
# #
...@@ -369,6 +372,16 @@ class chan(object): ...@@ -369,6 +372,16 @@ class chan(object):
# default represents default case for select. # default represents default case for select.
default = object() default = object()
# unbound chan.{send,recv,recv_}
_chan_send = chan.send
_chan_recv = chan.recv
_chan_recv_ = chan.recv_
if six.PY2:
# on py3 class.func gets the func; on py2 - unbound_method(func)
_chan_send = _chan_send.__func__
_chan_recv = _chan_recv.__func__
_chan_recv_ = _chan_recv_.__func__
# select executes one ready send or receive channel case. # select executes one ready send or receive channel case.
# #
# if no case is ready and default case was provided, select chooses default. # if no case is ready and default case was provided, select chooses default.
...@@ -418,12 +431,12 @@ def select(*casev): ...@@ -418,12 +431,12 @@ def select(*casev):
# send # send
elif isinstance(case, tuple): elif isinstance(case, tuple):
send, tx = case send, tx = case
if send.im_class is not chan: if im_class(send) is not chan:
panic("select: send on non-chan: %r" % (send.im_class,)) panic("select: send on non-chan: %r" % (im_class(send),))
if send.im_func is not chan.send.im_func: if send.__func__ is not _chan_send:
panic("select: send expected: %r" % (send,)) panic("select: send expected: %r" % (send,))
ch = send.im_self ch = send.__self__
ch._mu.acquire() ch._mu.acquire()
if 1: if 1:
ok = ch._trysend(tx) ok = ch._trysend(tx)
...@@ -436,16 +449,16 @@ def select(*casev): ...@@ -436,16 +449,16 @@ def select(*casev):
# recv # recv
else: else:
recv = case recv = case
if recv.im_class is not chan: if im_class(recv) is not chan:
panic("select: recv on non-chan: %r" % (ch.im_class,)) panic("select: recv on non-chan: %r" % (im_class(recv),))
if recv.im_func is chan.recv.im_func: if recv.__func__ is _chan_recv:
commaok = False commaok = False
elif recv.im_func is chan.recv_.im_func: elif recv.__func__ is _chan_recv_:
commaok = True commaok = True
else: else:
panic("select: recv expected: %r" % (recv,)) panic("select: recv expected: %r" % (recv,))
ch = recv.im_self ch = recv.__self__
ch._mu.acquire() ch._mu.acquire()
if 1: if 1:
rx_, ok = ch._tryrecv() rx_, ok = ch._tryrecv()
......
# -*- coding: utf-8 -*-
# Copyright (C) 2018 Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
# it under the terms of the GNU General Public License version 3, or (at your
# option) any later version, as published by the Free Software Foundation.
#
# You can also Link and Combine this program with other software covered by
# the terms of any of the Free Software licenses or any of the Open Source
# Initiative approved licenses and Convey the resulting work. Corresponding
# source of such a combination shall include the source code for all other
# software used.
#
# This program is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
"""compatibility in between py2/py3"""
from six import PY2
if PY2:
def im_class(f):
return f.im_class
# PY3
else:
def im_class(f):
return f.__self__.__class__
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment