I've run into this issue a couple of times. I want to inherit from a class in order to extend it's functionality. The problem is that the class is defined in c in a shared library and doesn't seem to be designed so that it will allow inheritance (no __class__ defined, etc).
For example the Client object from pysvn. -
import pysvn
-
class MyClient(pysvn._pysvn._Client):
-
pass
-
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: Error when calling the metaclass bases
cannot create 'builtin_function_or_method' instances
Is there already a soluion to this issue? My current thought is to create an Object Wrapper class as shown below to use in these situations. Any suggestions or better solutions? -
import pysvn
-
-
class ObjectWrapper(object):
-
def __init__(self, obj):
-
self._obj = obj
-
-
def __getattr__(self, name):
-
if not hasattr(self._obj, name):
-
raise AttributeError, ("'%s' has no attribute %s" %
-
(self.__class__.__name__, name))
-
else:
-
return getattr(self._obj, name)
-
-
def __setattr__(self, name, value):
-
if (name == "_obj" or not hasattr(self, "_obj") or
-
not hasattr(self._obj, name) or name in dir(self)):
-
return super(ObjectWrapper, self).__setattr__(name, value)
-
else:
-
return setattr(self._obj, name, value)
-
-
class MyClient(ObjectWrapper):
-
def __init__(self, config_dir='', foo=''):
-
# pysvn.Client() method returns a Client object
-
super(MyClient, self).__init__(pysvn.Client(config_dir))
-
self.foo = foo
-
-
def getFoo(self):
-
return self.foo
-
-
client = MyClient()
-
# call pysvn.Client method 'is_url'
-
client.is_url("file://test")
-
# call MyClient method 'getFoo'
-
client.getFoo()
-
3 6254
It may be more simple than that. I've used the following technique successfully for a while now: -
class DBConnectionWrapper(object):
-
def __init__(self, servername, username="", password="", autocommit=1, database=""):
-
odbcstring = "DSN=%s;UID=%s;PWD=%s" %(servername, username, password)
-
self.dbConnection = connect(odbcstring, autocommit=autocommit)
-
-
def __getattribute__(self, name):
-
"""Redirect method calls to the connection 'object'."""
-
try:
-
return object.__getattribute__(self, name)
-
except AttributeError:
-
# __getattribute__() only work for subtypes of __builtin__.object.
-
## return object.__getattribute__(self.dbConnection, name)
-
return eval("self.dbConnection.%s" %(name))
-
Thanks for the reply.
The __setattr__ is necessary to set wrapped object attributes on the wrapped object rather than the object wrapper (when assigning an attr directly and not calling a set method). This probably wasn't a concern for your DBConnectionWrapper. Consider the following example: -
class Foo(object):
-
def __init__(self, bar='default'):
-
self.bar = bar
-
def getUpperCaseBar(self):
-
return str(self.bar).upper()
-
-
class FooWrapper(ObjectWrapper):
-
def __init__(self, bar='default'):
-
ObjectWrapper.__init__(self, Foo(bar))
-
-
def extendFooFunction(self):
-
return "my function to extend Foo"
-
-
fw = FooWrapper()
-
fw.bar = "Hello"
-
print fw.getUpperCaseBar()
-
(Of course in this case we could just inherit from Foo rather than using a wrapper, this is just a simple example). This illustrates that without the ObjectWrapper __setattr__ you'll end up setting the bar attribute on the wrapper object rather than the wrapped object. Thus getUpperCaseBar() will print "DEFAULT" rather than "HELLO" because fw.bar is "Hello" but fw._obj.bar is still "default".
It's good to see that you approached the problem in a similar manner and that I'm not missing a more elegant solution. Cheers.
Here is an improvement to fix compatibility with objects that use the deprecated __methods__ and __members__ attributes.
Now it will show the expected result for dir(objectWrapperInstance), similar to what you would get if you had inherited from the wrapped object. -
class ObjectWrapper(object):
-
"""ObjectWrapper class redirects unhandled calls to wrapped object.
-
-
Intended as an alternative when inheritance from the wrapped object is not
-
possible. This is the case for some python objects implemented in c.
-
-
"""
-
def __init__(self, obj):
-
"""Set the wrapped object."""
-
super(ObjectWrapper, self).__setattr__('_obj', obj)
-
-
# __methods__ and __members__ are deprecated but still used by
-
# dir so we need to set them correctly here
-
methods = []
-
for nameValue in inspect.getmembers(obj, inspect.ismethod):
-
methods.append(nameValue[0])
-
super(ObjectWrapper, self).__setattr__('__methods__', methods)
-
-
def isnotmethod(object_):
-
return not inspect.ismethod(object_)
-
members = []
-
for nameValue in inspect.getmembers(obj, isnotmethod):
-
members.append(nameValue[0])
-
super(ObjectWrapper, self).__setattr__('__members__', members)
-
-
def __getattr__(self, name):
-
"""Redirect unhandled get attribute to self._obj."""
-
if not hasattr(self._obj, name):
-
raise AttributeError, ("'%s' has no attribute %s" %
-
(self.__class__.__name__, name))
-
else:
-
return getattr(self._obj, name)
-
-
def __setattr__(self, name, value):
-
"""Redirect set attribute to self._obj if necessary."""
-
# note that we don't want to call hasattr(self, name) or dir(self)
-
# we need to check if it is actually an attr on self directly
-
selfHasAttr = True
-
try:
-
super(ObjectWrapper, self).__getattribute__(name)
-
except AttributeError:
-
selfHasAttr = False
-
-
if (name == "_obj" or not hasattr(self, "_obj") or
-
not hasattr(self._obj, name) or selfHasAttr):
-
return super(ObjectWrapper, self).__setattr__(name, value)
-
else:
-
return setattr(self._obj, name, value)
-
Pete
Sign in to post your reply or Sign up for a free account.
Similar topics
by: Fabian Neumann |
last post by:
Hi!
I got a problem with font-family inheritance. Let's say I have CSS
definitions like:
p {
font:normal 10pt Verdana;
}
strong {
font:normal 14pt inherit;
|
by: Jeff Schmidt |
last post by:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello,
~ Ok, I've got some tables, and a style sheet that contains stuff to
format the table. The problem I'm having is, it appears that using...
|
by: bobsled |
last post by:
For class A to reuse functionality of a class B, A could either contains B
or inherits from B. When should pick which?
In a book the author says that "Don't inherit from a concrete class." Does...
|
by: chriss |
last post by:
Hi,
environment: Python 2.4, GNU/Linux, kernel 2.6.12.2
having subclassed 'Exception' I'm trying to call the initialiser
__init__(...) of the superclass Exception with 'super(..).__init__(..)'...
|
by: Slavyan |
last post by:
(I just started to learn C#.NET)
What's the syntax in c# for a class to inherit more than one class.
I know following syntax:
public class MyClass : MyOtherClass
{
}
but I need to inherit...
|
by: Mohammad-Reza |
last post by:
I wrote a component using class library wizard. In my component i want to in
order to RightToLeft property do some works.
I can find out if user set this property to Yes or No, But if He/She set it...
|
by: ad |
last post by:
We can inherit a class.
But if the class is the code behind, when we inherit it , can we inherit
it's aspx ahead together ?
|
by: Optimus |
last post by:
Hi everyone,
I currently develop an application in vs.net 2005 with vb.net.
I was trying to use typed dataset and I've got in trouble for
converting untyped dataset
into Typed DataSet. I don't...
|
by: GTalbot |
last post by:
Hello fellow comp.infosystems.www.authoring.stylesheets colleagues,
Imagine this situation:
#grand-parent-abs-pos
{
height: 400px;
position: absolute;
width: 600px;
}
|
by: lllomh |
last post by:
Define the method first
this.state = {
buttonBackgroundColor: 'green',
isBlinking: false, // A new status is added to identify whether the button is blinking or not
}
autoStart=()=>{
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: tracyyun |
last post by:
Hello everyone,
I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
|
by: Teri B |
last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course.
0ne-to-many. One course many roles.
Then I created a report based on the Course form and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: isladogs |
last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, Mike...
| |