Welcome, guest | Sign In | My Account | Store | Cart

Yet another attempt to deal with Interface concept in Python

Python, 80 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#
# for interface-methods non redefined in classes
#
class AbstractError:
	pass

#
# a kind of interface 
#
class Copyable:
	def copy(self):
		return self.__copy__() 
	def __interface__(self):		
		assert self.__class__.__dict__.has_key('__copy__')
		x = self.copy()
		if hasattr(self,'__cmp__') or hasattr(self,'__eq__'):						
			assert x==self
		assert x is not self
		
#
# Another kind of interface that require more elaborated 
# testing.
# __interface__ method only check that the testing stuff
# has really be done.
#
class MyStackInterface:
	def test_MyStackInterface(self, param1, param2):
		self.append(param1)
		self.append(param2)
		assert self.pop() == param2
		assert self.pop() == param1
		self.__tested = 1
	def __interface__(self):		
		assert self.__tested == 1
	def append(self, data):
		raise AbstractError
	def pop(self):
		raise AbstractError
		
		

#
#  A sample of dummy class that define our two interfaces
#
class XX(Copyable, MyStackInterface):
	def __init__(self):
		self.data = []
	def __copy__ (self):
		o = XX()
		o.data = self.data[:]
		return o
		
	def __eq__(self,other):
		return self.data == other.data
	def append(self,d):
		self.data.append(d)
	def pop(self):
		return self.data.pop()

#		
# Utilities functions for ensuring that classes well
# define interfaces.
#
def _test_interface(cl,obj):
	if cl.__dict__.has_key('__interface__'):
		cl.__interface__(obj)
	for i in cl.__bases__:
		_test_interface(i,obj)
		

def EnsureInterface(obj):
	_test_interface(obj.__class__, obj)
	

#
# and now we do the tests
#
x=XX()
x.test_MyStackInterface(0,'foo')
EnsureInterface(x)

People sometime says that lack of formal interface specification make Python not suited for programming in the large.

Since interfaces in languages like Java or C++ only deal with syntax checking I don't think this construct would be usefull for a dynamic language like Python.

So I suggest to replace this static checking by tests. The interface manage a test suite, and any class that want to define an interface must pass this test suite. A mechanism ensure that, for every interfaces, the tests have been passed.

Created by Sébastien Keim on Fri, 28 Sep 2001 (PSF)
Python recipes (4591)
Sébastien Keim's recipes (24)

Required Modules

  • (none specified)

Other Information and Tasks