diff options
authorValerii Ponomarov <>2019-11-22 01:24:13 +0530
committerValerii Ponomarov <>2019-11-22 13:12:13 +0530
commit037994f9835cafe248e8a78e4cb875f01116f1ef (patch)
parent082f516a33d14c836cd47293cb29c83ae80e294d (diff)
[py2to3] Add method to the base class for proper calling of it's methods
Lots of test classes are wrapped by the 'runs_on' decorator. This decorator replaces original test class with it's copy where parent class is original test class if we use py3. Such situation leads to the impossibility to use following approach in py3: super(SomeClass, some_class_instance).some_method() And, the above approach is py2/3 compatible approach for calling parent class's methods. The problem we face is that we fall into the unexpected recursion here. So, add 'get_super_method' to the base class, which detects such situation and returns proper method of a proper parent class. Also, fix test class located at 'glusterd/' module to have proof of concept. With this change 'test_peer_probe_status' test case becomes completely py2/3 compatible. Example of new method usage: @runs_on([['distributed'], ['glusterfs']]) class TestDecoratedClass(GlusterBaseClass): ... def setUp(self): self.get_super_method(self, 'setUp')() ... This approach must be used instead of existing calls of 'im_func' function if we want to support both at once - python2 and python3. Signed-off-by: Valerii Ponomarov <> Change-Id: I23f4462b64f9d4dd90812273f08fb756d073ab76
2 files changed, 28 insertions, 3 deletions
diff --git a/glustolibs-gluster/glustolibs/gluster/ b/glustolibs-gluster/glustolibs/gluster/
index b475eddd1..ae842b055 100644
--- a/glustolibs-gluster/glustolibs/gluster/
+++ b/glustolibs-gluster/glustolibs/gluster/
@@ -90,6 +90,32 @@ class GlusterBaseClass(unittest.TestCase):
volume_type = None
mount_type = None
+ @staticmethod
+ def get_super_method(obj, method_name):
+ """PY2/3 compatible method for getting proper parent's (super) methods.
+ Useful for test classes wrapped by 'runs_on' decorator which has
+ duplicated original test class [py3] as parent instead of the
+ base class as it is expected.
+ Example for calling 'setUp()' method of the base class from the
+ 'setUp' method of a test class which was decorated with 'runs_on':
+ @runs_on([['distributed'], ['glusterfs']])
+ class TestDecoratedClass(GlusterBaseClass):
+ ...
+ def setUp(self):
+ self.get_super_method(self, 'setUp')()
+ ...
+ """
+ if (getattr(super(obj.__class__, obj), method_name) != getattr(
+ obj, method_name)):
+ return getattr(super(obj.__class__, obj), method_name)
+ # NOTE(vponomar): we always have here just one base as 'obj' is
+ # expected to be renamed copy of it's parent.
+ return getattr(super(obj.__class__.__bases__[0], obj), method_name)
def inject_msg_in_gluster_logs(cls, msg):
"""Inject all the gluster logs on servers, clients with msg
diff --git a/tests/functional/glusterd/ b/tests/functional/glusterd/
index cc282de57..65e8db9ed 100644
--- a/tests/functional/glusterd/
+++ b/tests/functional/glusterd/
@@ -34,8 +34,7 @@ from glustolibs.gluster.peer_ops import (peer_probe, peer_status, peer_detach,
class TestPeerStatus(GlusterBaseClass):
def setUp(self):
- GlusterBaseClass.setUp.im_func(self)
+ self.get_super_method(self, 'setUp')()
# Performing peer detach
ret = peer_detach_servers(self.mnode, self.servers)
@@ -67,7 +66,7 @@ class TestPeerStatus(GlusterBaseClass):
"servers %s" % self.servers)"Peer probe success for detached "
"servers %s", self.servers)
- GlusterBaseClass.tearDown.im_func(self)
+ self.get_super_method(self, 'tearDown')()
def test_peer_probe_status(self):