473,575 Members | 3,507 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Hacking with __new__

Ok here's the problem, I'm modifying a 3rd party library (boto) to
have more specific exceptions. I want to change S3ResponseError into
about 30 more specific errors. Preferably I want to do this by
changing as little code as possible. I also want the new exceptions to
be a subclass of the old S3ResponseError so as to not break old code
that catches it. If I meet these two requirements I expect my
modification to make it into boto and then I won't have to worry about
maintaining a seperate version.

So thinking myself clever with python I thought I could change
S3ResponseError to have a __new__ method which returns one of the 30
new exceptions. That way none of the raise S3ResponseError code needs
changing. No problem. The trouble comes with those exceptions being
subclasses of S3ResponseError , because __new__ is called again and
goofs everything up.

I think there may be a way to solve this but after playing around in
the shell for a while, I give up. I'm less concerned with the original
problem than I am curious about the technical challenge. Can anyone
tell me if it's possible to do meet both of my requirements?

Thanks,
-Sandra

Here's my shell code if you want to play with it too (Bar is
S3ResponseError , Zoo is a more specific error, Foo is just the base
class of Bar.)
>>class Foo(object):
.... def __new__(cls, *args):
.... print 'Foo.__new__', len(args)
.... return super(Foo, cls).__new__(cl s, *args)
....
.... def __init__(self, a, b, c):
.... print 'Foo.__init__', 3
.... self.a = a
.... self.b = b
.... self.c = c
....
>>class Bar(Foo):
.... def __new__(cls, a, b, c, *args):
.... print 'Bar.__new__', len(args)
.... if args:
.... return super(Bar, cls).__new__(cl s, a, b, c, *args)
....
.... return Zoo(a, b, c, 7)
....
>>class Zoo(Bar):
.... def __init__(self, a, b, c, d):
.... print 'Zoo.__init__', 4
.... Foo.__init__(se lf, a, b, c)
.... self.d = d
....
>>Bar(1,2,3)
Bar.__new__ 0
Bar.__new__ 1
Foo.__new__ 4
Zoo.__init__ 4
Foo.__init__ 3
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: __init__() takes exactly 5 arguments (4 given)

Jul 24 '07 #1
5 1448
Sandra-24 <sa***********@ yahoo.comwrote:
So thinking myself clever with python I thought I could change
S3ResponseError to have a __new__ method which returns one of the 30
new exceptions. That way none of the raise S3ResponseError code needs
changing. No problem. The trouble comes with those exceptions being
subclasses of S3ResponseError , because __new__ is called again and
goofs everything up.
I think what you want for Bar is something more along the lines:

class Foo(object):
def __new__(cls, *args):
print 'Foo.__new__', len(args)
return super(Foo, cls).__new__(cl s, *args)

def __init__(self, a, b, c):
print 'Foo.__init__', 3
self.a = a
self.b = b
self.c = c

class Bar(Foo):
def __new__(cls, a, b, c, *args):
print 'Bar.__new__', len(args)
target = cls
if not args:
cls = Zoo
obj = super(Bar, cls).__new__(cl s, a, b, c, *args)
if args:
return obj

obj.__init__(a, b, c, 7)

class Zoo(Bar):
def __init__(self, a, b, c, d):
print 'Zoo.__init__', 4
Foo.__init__(se lf, a, b, c)
self.d = d

Bar(1,2,3)

Output from this is:

Bar.__new__ 0
Foo.__new__ 3
Zoo.__init__ 4
Foo.__init__ 3

Bar can instantiate a subclass, but to do that it wants to call the
constructor __new__ only for the base classes, and because it has
changed the type of the object being constructed it has to call __init__
explicitly.
Jul 24 '07 #2
Duncan Booth a écrit :
(snip)
I think what you want for Bar is something more along the lines:
(snip)
class Bar(Foo):
def __new__(cls, a, b, c, *args):
print 'Bar.__new__', len(args)
target = cls
You don't use 'target' anywhere...
if not args:
cls = Zoo
obj = super(Bar, cls).__new__(cl s, a, b, c, *args)
if args:
return obj

obj.__init__(a, b, c, 7)
IIRC, __new__ is supposed to return the newly created object - which you
are not doing here.

class Bar(Foo):
def __new__(cls, a, b, c, *args):
print 'Bar.__new__', len(args)
if not args:
cls = Zoo
obj = super(Bar, cls).__new__(cl s, a, b, c, *args)
if not args:
obj.__init__(a, b, c, 7)
return obj
Jul 24 '07 #3
On Jul 24, 5:20 am, Bruno Desthuilliers <bruno.
42.desthuilli.. .@wtf.websitebu ro.oops.comwrot e:
IIRC, __new__ is supposed to return the newly created object - which you
are not doing here.

class Bar(Foo):
def __new__(cls, a, b, c, *args):
print 'Bar.__new__', len(args)
if not args:
cls = Zoo
obj = super(Bar, cls).__new__(cl s, a, b, c, *args)
if not args:
obj.__init__(a, b, c, 7)
return obj
Thanks guys, but you are right Bruno, you have to return the newly
created object or you get:
>>b = Bar(1,2,3)
Bar.__new__ 0
Foo.__new__ 3
Zoo.__init__ 4
Foo.__init__ 3
>>b is None
True

However, if you return the object you get:
>>b = Bar(1, 2, 3)
Bar.__new__ 0
Foo.__new__ 3
Zoo.__init__ 4
Foo.__init__ 3
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: __init__() takes exactly 5 arguments (4 given)

Which is the same blasted error, because it seems to want to call init
on the returned object and it's calling it with 4 args :( Is there any
way around that?

Thanks,
-Sandra
Jul 24 '07 #4
Bruno Desthuilliers <br************ ********@wtf.we bsiteburo.oops. com>
wrote:
Duncan Booth a écrit :
(snip)
>I think what you want for Bar is something more along the lines:

(snip)
>class Bar(Foo):
def __new__(cls, a, b, c, *args):
print 'Bar.__new__', len(args)
target = cls
You don't use 'target' anywhere...
> if not args:
cls = Zoo
obj = super(Bar, cls).__new__(cl s, a, b, c, *args)
if args:
return obj

obj.__init__(a, b, c, 7)

IIRC, __new__ is supposed to return the newly created object - which you
are not doing here.
Yup. I committed that cardinal sin of checking the code and then tidying it
up by hand but not checking the tidied version. :(
Jul 24 '07 #5
On 7/24/07, Sandra-24 <sa***********@ yahoo.comwrote:
On Jul 24, 5:20 am, Bruno Desthuilliers <bruno.
42.desthuilli.. .@wtf.websitebu ro.oops.comwrot e:
IIRC, __new__ is supposed to return the newly created object - which you
are not doing here.

class Bar(Foo):
def __new__(cls, a, b, c, *args):
print 'Bar.__new__', len(args)
if not args:
cls = Zoo
obj = super(Bar, cls).__new__(cl s, a, b, c, *args)
if not args:
obj.__init__(a, b, c, 7)
return obj

Thanks guys, but you are right Bruno, you have to return the newly
created object or you get:
>b = Bar(1,2,3)
Bar.__new__ 0
Foo.__new__ 3
Zoo.__init__ 4
Foo.__init__ 3
>b is None
True

However, if you return the object you get:
>b = Bar(1, 2, 3)
Bar.__new__ 0
Foo.__new__ 3
Zoo.__init__ 4
Foo.__init__ 3
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: __init__() takes exactly 5 arguments (4 given)

Which is the same blasted error, because it seems to want to call init
on the returned object and it's calling it with 4 args :( Is there any
way around that?
__init__ is going to be called with the arguments passed to __new__
and there doesn't seem to be any way to affect that. Your only option
to make it not happen is for Zoo not to be a subclass of Bar.

Possible workarounds:
Each subclass of Bar needs a corresponding __new__

Each subclass of Bar needs a cooperating __init__ that detects (via
optional arguments) if it's being called by Bar.__new__ or directly
and noops in the second case.
Jul 24 '07 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
2301
by: Michele Simionato | last post by:
Let me show first how does it work for tuples: >>> class MyTuple(tuple): .... def __new__(cls,strng): # implicit conversion string of ints => tuple .... return super(MyTuple,cls).__new__(cls,map(int,strng.split())) >>> MyTuple('1 2') (1, 2) No wonder here, everything is fine. However, if I do the same for lists I get the...
9
6200
by: Felix Wiemann | last post by:
Sometimes (but not always) the __new__ method of one of my classes returns an *existing* instance of the class. However, when it does that, the __init__ method of the existing instance is called nonetheless, so that the instance is initialized a second time. For example, please consider the following class (a singleton in this case): >>>...
5
2493
by: could ildg | last post by:
As there is already __init__, why need a __new__? What can __new__ give us while __init__ can't? In what situations we should use __new__? And in what situations we must use __new__? Can __new__ take the place of __init__? Thanks.
3
2595
by: James Stroud | last post by:
Hello All, I'm running 2.3.4 I was reading the documentation for classes & types http://www.python.org/2.2.3/descrintro.html And stumbled on this paragraph: """ __new__ must return an object. There's nothing that requires that it return a
5
2148
by: Ken Schutte | last post by:
Hi, I'm been trying to create some custom classes derived from some of python's built-in types, like int and list, etc. I've run into some trouble, which I could explain with a couple simple examples. Lets say I want an int-derived class that is initilized to one greater than what it's constructor is given: class myint(int): def...
18
1697
by: Paulo da Silva | last post by:
Sorry to put here too many questions about __init__ __new__ stuff but I always found a new problem when using them. I have searched for simple __new__ docs on how to do the basic things but find none. After trying the solutions people gently posted here (thanks) I run into new trouble when I go with further development. Here is the new...
1
1195
by: Frank Benkstein | last post by:
Hi, the behaviour I always observed when creating instances by calling the class A is that '__init__' is always only called when the object returned by A.__new__ is an instance of A. This can be observed by the following code: class A(object): def __new__(cls, *args, **kwds): print "A.__new__", args, kwds
4
3527
by: Steven D'Aprano | last post by:
When you call a new-style class, the __new__ method is called with the user-supplied arguments, followed by the __init__ method with the same arguments. I would like to modify the arguments after the __new__ method is called but before the __init__ method, somewhat like this: .... def __new__(cls, *args): .... print...
3
2764
by: Torsten Mohr | last post by:
Hi, i have some questions related to new style classes, they look quite useful but i wonder if somebody can give me an example on constructors using __new__ and on using __init__ ? I just see that when using it i can't give parameters to __new__ and when i additionally define __init__ then __new__ is not called.
0
7845
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
1
7868
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6515
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5664
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5338
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3778
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3797
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2286
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1382
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.