Issue672115
Created on 2003-01-21 22:45 by glchapman, last changed 2016-12-07 19:15 by eli.collins.
Files | ||||
---|---|---|---|---|
File name | Uploaded | Description | Edit | |
typeobject.c.diff | glchapman, 2003-02-05 02:39 |
Messages (18) | |||
---|---|---|---|
msg14163 - (view) | Author: Greg Chapman (glchapman) | Date: 2003-01-21 22:45 | |
I'm not entirely sure this is a bug, but I think it is surprising: Python 2.3a1 (#38, Dec 31 2002, 17:53:59) [MSC v.1200 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> class A(object): ... pass ... >>> class B(object): ... pass ... >>> B.__bases__ = (A,) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: __bases__ assignment: 'A' deallocator differs from 'object' It seems like you should be able to change the __bases__ of a new-style class (implemented in Python) which inherits directly from object to another new-style class. (Will the deallocator issue ever come into play if the only types involved are HEAPTYPES and object as the ultimate base?) |
|||
msg14164 - (view) | Author: Michael Hudson (mwh) ![]() |
Date: 2003-01-22 11:50 | |
Logged In: YES user_id=6656 I agree this is a bit surprising. When I was writing this code I went for the conservative-as-possible approach as I didn't want to introduce instabilities to Python. It certainly may be that I've overdone it. In this case I probably have; if the tp_dealloc of the class being adjusted is subtype_dealloc and the tp_dealloc that ultimately gets invoked is the same we're probably OK. But I'm not sure and it's been a while since I thought about this. It also happens that my motivating use-case for this isn't troubled by this restriction. I don't understand your last, parenthetical, comment. HEAPTYPES as such doesn't come into it, does it? You might be right that we don't need to worry about tp_dealloc if the ultimate solid_base doesn't change and all the tp_deallocs on the way there are subtype_dealloc... |
|||
msg14165 - (view) | Author: Greg Chapman (glchapman) | Date: 2003-01-23 17:03 | |
Logged In: YES user_id=86307 Sorry about the parenthetical comment; I think what I was trying to say is basically what you have in your last paragraph. As for use cases, I don't have any myself (I ran into this with some test code for a metaclass which "overrides" __bases__). However, grepping through the standard library, I note that one place where assignment to __bases__ is used is in xmlrpclib.SlowParser. It appears to me that if SlowParser and xmllib.XMLParser (neither of which has a base class) were converted to new-style classes, the assignment to __bases__ would generate this exception. Of course, that shouldn't be too hard to work around if that turns out to be necessary. |
|||
msg14166 - (view) | Author: Michael Hudson (mwh) ![]() |
Date: 2003-01-31 18:09 | |
Logged In: YES user_id=6656 Are you interested in working up a patch for this? Hacking this kind of stuff requires motivation I'm not sure I can drum up in time for 2.3... |
|||
msg14167 - (view) | Author: Greg Chapman (glchapman) | Date: 2003-02-05 02:39 | |
Logged In: YES user_id=86307 Well, I wrote a small patch which I'm attaching. However, I can't say that I'm partcularly confident in it. It works for the simple cases I've been able to think of (and for test_descr.py), but looking at typeobject.c, I get the nagging feeling that a lot more tests are required to be sure it's OK. The problem is, I'm just not sure what they (the tests) are. |
|||
msg14168 - (view) | Author: Michael Hudson (mwh) ![]() |
Date: 2003-02-05 14:22 | |
Logged In: YES user_id=6656 Mhmm. That looks OK to me (after realizing that solid_base worries about __slots__). But I don't know how one can be sure :-( |
|||
msg14169 - (view) | Author: Michael Hudson (mwh) ![]() |
Date: 2005-03-16 13:22 | |
Logged In: YES user_id=6656 Two years on, I think about this again. Still here? :) The motivating thought is that: class A(object): pass class B(object): pass B.__bases__ = (A,) and class A(object): pass class B(A): pass should be equivalent. An issue that hadn't occurred to me before is that in the first example both A and B have a __dict__ (and __weakref__) descriptor, and in the second B doesn't. Should B's __dict__ descriptor be removed on the __bases__ assignment? |
|||
msg14170 - (view) | Author: Greg Chapman (glchapman) | Date: 2005-03-28 22:54 | |
Logged In: YES user_id=86307 Still here -- sorry not to reply sooner. I couldn't actually remember what my patch was supposed to do, or more specifically I couldn't remember what it did to check that this sort of change in __bases__ was safe. So, anyway, I finally got around to looking at the patch again, and at typeobject.c, and I can say that I'm less sure of the subtleties involved now than I was then. Anyway, with that caveat, what you suggest sounds reasonable enough, though I suppose you'd have to reinsert a dict descriptor if __bases__ was later changed back to (object,). (It looks like the patch would have supported changing __bases__ back to (object,), though perhaps it shouldn't.) It seems to me nobody is particularly troubled by this limitation on assignment to __bases__ (perhaps you know differently?). Maybe it's best just to close this as "not a bug." |
|||
msg14171 - (view) | Author: Michael Hudson (mwh) ![]() |
Date: 2005-03-29 12:21 | |
Logged In: YES user_id=6656 Well, my motivation is to better understand what's going on in typeobject.c. There are a number of unclear sections (to put it mildly) and undocumented assumptions and this makes it hard to work out whether things (like this) are bugs or not. I'm now fairly confident that the line "compatible_for_assigment(new_base, self->tp_base)" is asking the right question (and, thus, your patch is not really correct, though I doubt it's actually unsafe). The spelling is a bit funny though. This issue in and of itself isn't that high a priority, but understanding (and documenting that understanding) of typeobject.c does seem worth working on... |
|||
msg70132 - (view) | Author: lorph (lorph) | Date: 2008-07-22 02:58 | |
Is anyone still working on this? It seems like an oddity of python that has been a stumbling block for me to create a super reload. I've found that i am able to bypass this problem by creating the following definition: class object(object):pass However, this feels like an ugly hack. |
|||
msg70133 - (view) | Author: Michael Hudson (mwh) ![]() |
Date: 2008-07-22 03:11 | |
Another 3 and a bit years on <wink> I still think my comment http://bugs.python.org/msg14169 is the crux of the issue. It's even relevant to your class object(object): pass hack! I'm not at all likely to work on this any time soon myself. |
|||
msg86225 - (view) | Author: Lars (farcat) | Date: 2009-04-21 09:13 | |
in my project i need to be able to let the user dynamically make and remove inheritance relationships between classes and in my testing i think i have run into this issue assigning to __bases__. the class object(object): pass trick seems to work, but i can't really oversee the consequenses. I also saw another variation which might be the same issue: A= type("A", (object,), {'one': 1}) B= type("B", (object,), {'two': 2}) C= type("C", (object,), {'three': 3}) A = type("A",(A,B),{}) print dir(A) print A.__bases__ print '-----------------------------------' A.__bases__ = (B,C) print dir(A) print A.__bases__ print '-----------------------------------' no exceptions, but the second dir(A) shows that A has lost its attribute 'one' if the class object(object) trick is not safe, is there a way to get the dynamic inheritance behaviour in another way, e.g. through metaclasses? |
|||
msg88508 - (view) | Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * ![]() |
Date: 2009-05-29 14:07 | |
Lars, I think that your question has a simple explanation, and is not related to the original issue: - On 4th line, the variable named "A" is bound to a new type object. This type has no attribute by itself. - The first dir(A) displays the attributes of the bases class, which are the previous A and B: you see ['one', 'two'] - The second dir(A) displays the attributes of the bases class, which are B and C: you see ['two', 'three'] The instruction "A = type(...)" causes A to refer to another object; it does not change the object previously contained in A. |
|||
msg88569 - (view) | Author: Lars (farcat) | Date: 2009-05-30 08:05 | |
ok, i see what you mean, for me at this time the most important question is whta does class object(object) pass do, why can i change baseclasses after i redeclare object this way, and will it get me into trouble when i use this to let users dynamically define classes and inheritence relationships? cheers |
|||
msg106633 - (view) | Author: Hari Krishna Dara (Hari.Krishna.Dara) | Date: 2010-05-28 02:30 | |
I just hit up on this same bug and the "class object(object): pass" workaround worked fine. I too would like to know how safe this workaround is, could someone more insightful please comment on this? |
|||
msg154116 - (view) | Author: Adam Venturella (aventurella) | Date: 2012-02-24 06:31 | |
I too just found the same issue, dunno if it was settled on as being a bug per se. "class object(object): pass" Also worked for me. I don't feel great about doing that though. So I opted for more verbose name as not to collide with "object" I have to wonder, since it's been 9 years, if all of us finding this issue are guilty of doing it wrong =) |
|||
msg189987 - (view) | Author: Mark Lawrence (BreamoreBoy) * | Date: 2013-05-25 17:52 | |
Has any work been done on typeobject.c to render this obsolete? Failing that are there any souls brave enough to take on typeobject.c? |
|||
msg270220 - (view) | Author: Memeplex (memeplex) | Date: 2016-07-12 01:59 | |
I understand Michael's comment http://bugs.python.org/issue672115#msg14169 but I'm failing to see how it's directly related to this issue: as Michael himself said it's even relevant for the object-subclass-object hack or for any hierarchy whatsoever. Is the comment warning about the entire writable-bases idea? It feels to me like the behavior should be consistently extended or consistently banned, but currently some cases work, another cases don't, and there seems to be no clear rationale supporting this state of affairs. Am I wrong? |
History | |||
---|---|---|---|
Date | User | Action | Args |
2016-12-07 19:15:51 | eli.collins | set | nosy:
+ eli.collins |
2016-07-12 01:59:34 | memeplex | set | nosy:
+ memeplex messages: + msg270220 |
2015-06-11 10:26:13 | pitrou | set | type: behavior -> enhancement versions: + Python 3.6, - Python 3.5 |
2015-06-10 14:26:08 | borisompol | set | nosy:
+ borisompol |
2014-03-13 17:14:44 | flox | set | nosy:
+ flox versions: + Python 3.5, - Python 3.4 |
2014-02-03 17:10:09 | BreamoreBoy | set | nosy:
- BreamoreBoy |
2013-05-27 12:05:48 | lukasz.langa | set | versions: + Python 3.4, - Python 3.1, Python 2.7, Python 3.2 |
2013-05-27 12:05:33 | lukasz.langa | set | nosy:
+ lukasz.langa |
2013-05-25 17:52:05 | BreamoreBoy | set | nosy:
+ BreamoreBoy messages: + msg189987 |
2012-10-22 13:22:09 | krzysiekj | set | nosy:
+ krzysiekj |
2012-06-26 19:45:25 | florian-rathgeber | set | nosy:
+ florian-rathgeber |
2012-03-31 23:41:32 | pitrou | set | assignee: mwh -> nosy: + benjamin.peterson |
2012-02-24 06:31:04 | aventurella | set | nosy:
+ aventurella messages: + msg154116 |
2010-08-17 23:03:31 | BreamoreBoy | set | stage: needs patch type: behavior versions: + Python 3.1, Python 2.7, Python 3.2, - Python 2.3 |
2010-05-28 02:30:55 | Hari.Krishna.Dara | set | nosy:
+ Hari.Krishna.Dara messages: + msg106633 |
2009-05-30 08:05:08 | farcat | set | messages: + msg88569 |
2009-05-29 14:07:52 | amaury.forgeotdarc | set | nosy:
+ amaury.forgeotdarc messages: + msg88508 |
2009-04-21 09:13:22 | farcat | set | nosy:
+ farcat messages: + msg86225 |
2008-07-22 03:11:18 | mwh | set | messages: + msg70133 |
2008-07-22 02:58:26 | lorph | set | nosy:
+ lorph messages: + msg70132 |
2003-01-21 22:45:40 | glchapman | create |