472,978 Members | 2,236 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,978 software developers and data experts.

unable to inherit

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.

Expand|Select|Wrap|Line Numbers
  1. import pysvn
  2. class MyClient(pysvn._pysvn._Client):
  3.     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?

Expand|Select|Wrap|Line Numbers
  1. import pysvn
  3. class ObjectWrapper(object):
  4.     def __init__(self, obj):
  5.         self._obj = obj
  7.     def __getattr__(self, name):
  8.         if not hasattr(self._obj, name):
  9.             raise AttributeError, ("'%s' has no attribute %s" %
  10.                                    (self.__class__.__name__, name))
  11.         else:
  12.             return getattr(self._obj, name)
  14.     def __setattr__(self, name, value):
  15.         if (name == "_obj" or not hasattr(self, "_obj") or
  16.             not hasattr(self._obj, name) or name in dir(self)):
  17.             return super(ObjectWrapper, self).__setattr__(name, value)
  18.         else:
  19.             return setattr(self._obj, name, value)
  21. class MyClient(ObjectWrapper):
  22.     def __init__(self, config_dir='', foo=''):
  23.         # pysvn.Client() method returns a Client object
  24.         super(MyClient, self).__init__(pysvn.Client(config_dir))
  25.         self.foo = foo
  27.     def getFoo(self):
  28.         return self.foo
  30. client = MyClient()
  31. # call pysvn.Client method 'is_url'
  32. client.is_url("file://test")
  33. # call MyClient method 'getFoo'
  34. client.getFoo()
Oct 19 '07 #1
3 6254
6,596 Expert 4TB
It may be more simple than that. I've used the following technique successfully for a while now:
Expand|Select|Wrap|Line Numbers
  1. class DBConnectionWrapper(object):
  2.     def __init__(self, servername, username="", password="", autocommit=1, database=""):
  3.         odbcstring = "DSN=%s;UID=%s;PWD=%s" %(servername, username, password)
  4.         self.dbConnection = connect(odbcstring, autocommit=autocommit)
  6.     def __getattribute__(self, name):
  7.         """Redirect method calls to the connection 'object'."""
  8.         try:
  9.             return object.__getattribute__(self, name)
  10.         except AttributeError:
  11.             # __getattribute__() only work for subtypes of __builtin__.object.
  12. ##            return object.__getattribute__(self.dbConnection, name)
  13.             return eval("self.dbConnection.%s" %(name))
Oct 19 '07 #2
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:

Expand|Select|Wrap|Line Numbers
  1. class Foo(object):
  2.     def __init__(self, bar='default'):
  3.         self.bar = bar
  4.     def getUpperCaseBar(self):
  5.         return str(self.bar).upper()
  7. class FooWrapper(ObjectWrapper):
  8.     def __init__(self, bar='default'):
  9.         ObjectWrapper.__init__(self, Foo(bar))
  11.     def extendFooFunction(self):
  12.         return "my function to extend Foo"
  14. fw = FooWrapper()
  15. fw.bar = "Hello"
  16. 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.
Oct 23 '07 #3
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.

Expand|Select|Wrap|Line Numbers
  1. class ObjectWrapper(object):
  2.     """ObjectWrapper class redirects unhandled calls to wrapped object.
  4.     Intended as an alternative when inheritance from the wrapped object is not
  5.     possible.  This is the case for some python objects implemented in c.
  7.     """
  8.     def __init__(self, obj):
  9.         """Set the wrapped object."""
  10.         super(ObjectWrapper, self).__setattr__('_obj', obj)
  12.         # __methods__ and __members__ are deprecated but still used by
  13.         # dir so we need to set them correctly here
  14.         methods = []
  15.         for nameValue in inspect.getmembers(obj, inspect.ismethod):
  16.             methods.append(nameValue[0])
  17.         super(ObjectWrapper, self).__setattr__('__methods__', methods)
  19.         def isnotmethod(object_):
  20.             return not inspect.ismethod(object_)
  21.         members = []
  22.         for nameValue in inspect.getmembers(obj, isnotmethod):
  23.             members.append(nameValue[0])        
  24.         super(ObjectWrapper, self).__setattr__('__members__', members)
  26.     def __getattr__(self, name):
  27.         """Redirect unhandled get attribute to self._obj."""
  28.         if not hasattr(self._obj, name):
  29.             raise AttributeError, ("'%s' has no attribute %s" %
  30.                                    (self.__class__.__name__, name))
  31.         else:
  32.             return getattr(self._obj, name)
  34.     def __setattr__(self, name, value):
  35.         """Redirect set attribute to self._obj if necessary."""
  36.         # note that we don't want to call hasattr(self, name) or dir(self)
  37.         # we need to check if it is actually an attr on self directly
  38.         selfHasAttr = True
  39.         try:
  40.             super(ObjectWrapper, self).__getattribute__(name)
  41.         except AttributeError:
  42.             selfHasAttr = False
  44.         if (name == "_obj" or not hasattr(self, "_obj") or
  45.             not hasattr(self._obj, name) or selfHasAttr):
  46.             return super(ObjectWrapper, self).__setattr__(name, value)
  47.         else:
  48.             return setattr(self._obj, name, value)
Nov 26 '07 #4

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 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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.