orderedstuf fails where stuf works
I created a simple subclass of stuf
. It works fine. But when I tried to base it on orderedstuf
instead (in order to print the fields in a more attractive and comprehensible order), it fails spectacularly.
from stuf import stuf, orderedstuf
class User(stuf):
def __init__(self, **kwargs):
self.name = kwargs.get('name', None)
self.email = kwargs.get('email', None)
print User(name='Joe')
class OUser(orderedstuf):
def __init__(self, **kwargs):
self.name = kwargs.get('name', None)
self.email = kwargs.get('email', None)
print OUser(name='Moe')
Result:
User([('name', 'Joe'), ('email', None)])
Traceback (most recent call last):
File "/Users/jeunice/pytest/pypi/wtest.py", line 74, in <module>
print OUser(name='Moe')
File "/Users/jeunice/pytest/pypi/wtest.py", line 71, in __init__
self.name = kwargs.get('name', None)
File "/Library/Python/2.7/site-packages/stuf/_core.py", line 59, in __setattr__
self[key] = value
File "/Library/Python/2.7/site-packages/stuf/desc.py", line 36, in __get__
return self if this is None else self._set(this)
File "/Library/Python/2.7/site-packages/stuf/desc.py", line 28, in _set
return setter(this, self.name, self.method(this))
... hundreds of repetitive lines omitted...
File "/Library/Python/2.7/site-packages/stuf/desc.py", line 36, in __get__
return self if this is None else self._set(this)
File "/Library/Python/2.7/site-packages/stuf/desc.py", line 28, in _set
return setter(this, self.name, self.method(this))
File "/Library/Python/2.7/site-packages/stuf/_core.py", line 136, in __getitem__
return getitem(self)
File "/Library/Python/2.7/site-packages/stuf/_core.py", line 27, in __getattr__
if key == 'iteritems':
RuntimeError: maximum recursion depth exceeded in cmp
Comments (6)
-
reporter -
repo owner -
assigned issue to
-
assigned issue to
-
repo owner You need to call super i.e.:
from stuf import stuf, orderedstuf class User(stuf): def __init__(self, **kwargs): self.name = kwargs.get('name', None) self.email = kwargs.get('email', None) print User(name='Joe') class OUser(orderedstuf): def __init__(self, **kwargs): super(OUser, self).__init__(**kwargs) self.name = kwargs.get('name', None) self.email = kwargs.get('email', None) print OUser(name='Moe')
-
repo owner - changed status to resolved
-
reporter I accept "you need to call superclass initializer, doofus!" as a proper solution. DUH.
I should be doing the same thing for
User
. Not doing so is sloppy. But as a teaching moment, any insight why only the first one squeaks by? I'm not seeing it.FWIW, the final cleaned-up code follows.
from stuf import stuf, orderedstuf from say import say class User(stuf): def __init__(self, **kwargs): super(User, self).__init__(**kwargs) self.setdefault('name', None) self.setdefault('email', None) say> User(name='Joe') class OUser(orderedstuf): def __init__(self, **kwargs): super(OUser, self).__init__() self.name = kwargs.get('name', None) self.email = kwargs.get('email', None) say> OUser(name='Moe')
yields the proper result on both Python 2.7 and 3.3:
User(name='Joe', email=None) OUser(name='Moe', email=None)
-
repo owner orderedstuf
inherits fromwrapstuf
, which has to initialize a_wrapped
variable in its__init__
. Unlesssuper
is called, that__init__
doesn't get called and_wrapped
doesn't get initialized leading to the infinite loop as the object looks for a_wrapped
variable that's never there.When
orderedstuf
was originally coded, subclassingOrderedDict
was a pain. I vaguely recall the rationale for this was because its author (probably Raymond Hettinger) believed forcing reimplemention of key methods in a subclass leads to better inheritance hierarchies. Since I wanted a minimal implementation,orderedstuf
wrapsOrderedDict
rather than subclassing it. It stores the wrappedOrderedDict
in the_wrapped
variable. Depending upon if arguments are passed to the class constructor, theOrderedDict
can be empty or populated. The_mapping
class variable points to the type of data structure being mapped, in this caseOrderedDict
. - Log in to comment
I am using the latest drop on PyPI, btw:
0.9.10