Skip to content

LW KeyedTuples have instance dicts (ineffective __slots__) #3420

Closed
@sqlalchemy-bot

Description

@sqlalchemy-bot

Migrated issue, originally created by Sebastian Bank (@xflr6)

import sqlalchemy
import sqlalchemy.orm

engine = sqlalchemy.create_engine('sqlite://')
session = sqlalchemy.orm.Session(engine)
result = session.query(sqlalchemy.func.now())[0]

result.__dict__  # should raise AttributeError

print('\n'.join('%s\t%s' % (getattr(cls, '__slots__', None), cls)
    for cls in result.__class__.mro()))
# ()	<class 'sqlalchemy.util._collections.result'>
# ()	<class 'sqlalchemy.util._collections._LW'>
# None	<class 'sqlalchemy.util._collections.AbstractKeyedTuple'>
# None	<type 'tuple'>
# None	<type 'object'>

Note that __slots__ only works if every class along the mro spares instance __dict__s.
__slots__ = () for sqlalchemy.util._collections.AbstractKeyedTuple shoud fix this.

Activity

sqlalchemy-bot

sqlalchemy-bot commented on May 14, 2015

@sqlalchemy-bot
CollaboratorAuthor

Changes by Sebastian Bank (@xflr6):

  • edited description
sqlalchemy-bot

sqlalchemy-bot commented on May 14, 2015

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

  • The "lightweight named tuple" used when a :class:.Query returns
    rows failed to implement __slots__ correctly such that it still
    had a __dict__. This is resolved, but in the extremely
    unlikely case someone was assigning values to the returned tuples,
    that will no longer work.
    fixes LW KeyedTuples have instance dicts (ineffective __slots__) #3420

64c1f2e

sqlalchemy-bot

sqlalchemy-bot commented on May 14, 2015

@sqlalchemy-bot
CollaboratorAuthor

Changes by Michael Bayer (@zzzeek):

  • changed status to closed
sqlalchemy-bot

sqlalchemy-bot commented on May 14, 2015

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

thanks for catching that. countdown to someone was assigning to the tuple in 5..4..

sqlalchemy-bot

sqlalchemy-bot commented on May 15, 2015

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

.. 3... 2.. 1.. GO !!! https://groups.google.com/forum/#!topic/sqlalchemy/syWt_EZqCbk

this user is already getting an error even without the change here because they want to set one of the actual named attributes.

sqlalchemy-bot

sqlalchemy-bot commented on May 15, 2015

@sqlalchemy-bot
CollaboratorAuthor

Sebastian Bank (@xflr6) wrote:

Uh, you really know your users damn well!

I think Python even raises with new attributes (with and without the change).
I was curious if the change affects the benchmarks from the docs (maybe for some that would count as argument for/against __slots__).

sqlalchemy-bot

sqlalchemy-bot commented on May 15, 2015

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

__slots__ doesn't have a huge impact on speed, it is very useful for keeping memory under control though. The amount of memory that was being wasted throughout huge parts of SQLA on dictionaries that were hardly needed is why I put a lot of __slots__ in 1.0.

sqlalchemy-bot

sqlalchemy-bot commented on Sep 18, 2015

@sqlalchemy-bot
CollaboratorAuthor

Rodrigo Menezes (@rclmenezes) wrote:

Awww mannnn. You caught me :)

I assigned some helper lambdas to the returning rows:

class MyQuery(Query):
    def __iter__(self):
        return (self.decorate(r) for r in Query.__iter__(q) )
    
    handy_lambda_1 = lambda r: stuff
    handy_lambda_2 = lambda r: more_stuff
    
    def decorate(self, row):
        row.handy_lambda_1 = handy_lambda_1
        row.handy_lambda_2 = handy_lambda_2
        return row

MySession = scoped_session(
    sessionmaker(
        extension=ZopeTransactionExtension(),
        query_cls=MyQuery
    )
)

Any chance we'll get row_cls as an option to sessionmaker? I found these helper lambdas super useful in certain scenarios.

sqlalchemy-bot

sqlalchemy-bot commented on Sep 18, 2015

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

you can use Column Bundles and assign any kind of ORM-level processing to column-loads that you'd want.

sqlalchemy-bot

sqlalchemy-bot commented on Sep 18, 2015

@sqlalchemy-bot
CollaboratorAuthor

Michael Bayer (@zzzeek) wrote:

for interception of objects as they are loaded you can use the load event.

sqlalchemy-bot

sqlalchemy-bot commented on Sep 18, 2015

@sqlalchemy-bot
CollaboratorAuthor

Rodrigo Menezes (@rclmenezes) wrote:

Whoa! Column bundles are great. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @sqlalchemy-bot

        Issue actions

          LW KeyedTuples have instance dicts (ineffective __slots__) · Issue #3420 · sqlalchemy/sqlalchemy