On 05/30/2016 04:57 AM, 'Pankaj Gupta' via sqlalchemy wrote:
> I'm facing exactly same issue.
>
> It worked in past very well (below 1.0) and was very useful to update
> attribute or add new attributes (temporarily), now i can neither update
> not add new attributes.
>
> I'm wondering if someone can help us to port to later release or give
> some guidance for us to make it work.
The Query object is subclassable, here's a naive implementation of a
wrapper for that tuple:
from sqlalchemy.orm.query import Query
class WritableKeyedTuple(object):
def __init__(self, elem):
self._elem = elem
# TODO: this is slow, come up with a faster object
# that is still writable.
def __getattr__(self, key):
return getattr(self._elem, key)
def __repr__(self):
inner = [
(key, getattr(self._elem, key))
for key in self._elem.keys()
]
outer = [
(key, getattr(self, key))
for key in dir(self) if not key.startswith("_")
]
return "WritableKeyedTuple(%s)" % (
", ".join(
"%s=%s" % (key, value) for
(key, value) in inner + outer
)
)
class WritableTupleQuery(Query):
def __iter__(self):
it = super(WritableTupleQuery, self).__iter__()
cdesc = self.column_descriptions
if len(cdesc) > 1 or not isinstance(cdesc[0]['type'], type):
return (
WritableKeyedTuple(elem)
for elem in it
)
else:
return it
if __name__ == '__main__':
from sqlalchemy import create_engine, Column, Integer
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
x = Column(Integer)
y = Column(Integer)
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
Session = sessionmaker(bind=e, query_cls=WritableTupleQuery)
s1 = Session()
s1.add_all([A(x=1, y=2), A(x=3, y=4)])
s1.commit()
for im_an_entity in s1.query(A):
print im_an_entity
for im_a_tuple in s1.query(A.x, A.y):
im_a_tuple.supplementary = 'hi'
print im_a_tuple
for im_a_tuple in s1.query(A.x):
im_a_tuple.supplementary = 'hi'
print im_a_tuple
>
> Thanks,
> -Pankaj
>
> On Friday, May 15, 2015 at 7:26:16 PM UTC+5:30, Antoine Leclair wrote:
>
> Hi all,
>
> I recently tried to update SQLAlchemy from 0.9.4 to 1.0.4 in a
> client's project. However, I run into an error that is not there
> with 0.9.4.
>
> It happens for this type of query:
>
> q = DBSession.query(User) \
> .filter(User.profile_id.in_(profile_ids)) \
> .join(Profile)
> q = q.outerjoin(
> CouplePhoto,
> and_(
> User.profile_id==CouplePhoto.profile_id,
> CouplePhoto.avatar==True
> )
> )
> q = q.with_entities(User.profile_id, User.given_name, User.zipcode,
> CouplePhoto.filename, User.gender, Profile.sex)
> users_data = q.all()
> for u in users_data:
> if u.filename:
> *# the next line causes the error in 1.0.4*
> * u.filename = 'something'*
>
> In 0.9.4, the type of "u" was "KeyedTuple" and in 1.0.4, it's
> "result". The error is "AttributeError: can't set attribute".
>
> The goal of this assignation is to recompute the filename according
> to the original filename (to show a thumb instead of original). It
> is not saved in the database.
>
> Now, I know this is not necessarily good design and I would not have
> done it that way myself. But the code base is probably full of this
> type of thing, mixed with business logic, and trying to fix them is
> clearly not doable in the short term.
>
> And we have to update SQLAlchemy, because some circular reference
> issue was fixed when using Alembic somewhere between 0.9.4 and 1.0.4.
>
> Is there anything I should be aware of to help with this?
>
> Thanks in advance.
>
> --
> 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+...@googlegroups.com
> <mailto:
sqlalchemy+...@googlegroups.com>.
> To post to this group, send email to
sqlal...@googlegroups.com
> <mailto:
sqlal...@googlegroups.com>.
> Visit this group at
https://groups.google.com/group/sqlalchemy.
> For more options, visit
https://groups.google.com/d/optout.