Hi,

I've written a class decorator to define a boilerplate __init__ on some of 
my models that inherit from a declarative_base superclass. The problem is 
that sqlalchemy.orm.instrumentation._generate_init() has already installed 
an __init__ and when I overwrite that, things break with "object has no 
attribute '_sa_instance_state'" exceptions. I've provided a sample below. 
It actually throws a different exception than my code but I think the root 
issue is the same, that is, my __init__ replaced the generated one and so 
the ClassManager events are not being emitted.

Is there some blessed way to add an __init__ method after a class is 
already defined or is that just impossible with sqlalchemy's 
metaprogramming environment?

Love the library. Very powerful and excellent documentation. Thanks.
Eric

$ python
Python 2.7.10 (default, May 26 2015, 04:16:29) 
[GCC 5.1.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import psycopg2
>>> import sqlalchemy
>>> 
>>> psycopg2.__version__
'2.6 (dt dec pq3 ext lo64)'
>>> conn = psycopg2.connect("dbname=dispatch_dev")
>>> cur = conn.cursor()
>>> cur.execute("SELECT version();")
>>> cur.fetchone()
('PostgreSQL 9.4.4 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 
5.1.0, 64-bit',)
>>> 
>>> sqlalchemy.__version__
'0.9.7'
>>> 
>>> from collections import OrderedDict
>>> from decimal import Decimal
>>> from sqlalchemy import Column, Integer, Numeric
>>> from sqlalchemy.ext.declarative import declarative_base
>>> 
>>> def licensed(licenses):
...     def decorate(cls):
...         def ___init__(self, **kwargs):
...             for k, v in self.licenses.items():
...                 kwargs.setdefault('{}_license_rate'.format(k), v)
...             super(cls, self).__init__(**kwargs)
...         cls.__init__ = ___init__
...         for k, v in licenses.items():
...             licenses[k] = Decimal(v)
...         cls.licenses = licenses
...         for license in licenses:
...             setattr(cls, '{}_license_rate'.format(license), Column(
Numeric, nullable=False))
...         return cls
...     return decorate
... 
>>> 
>>> Base = declarative_base()
>>> 
>>> @licensed(OrderedDict((('foo', 100), ('bar', 150))))
... class Instance_Link(Base):
...     __tablename__ = 'instance_link'
...     id = Column(Integer, primary_key=True)
... 
>>> Instance_Link(foo_license_rate=50)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in ___init__
  File 
"(...)/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", 
line 526, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "(...)/env/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", 
line 225, in __set__
    self.impl.set(instance_state(instance),
AttributeError: 'NoneType' object has no attribute 'set'
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to