On Wed, Jan 10, 2018 at 1:03 PM, Matt Schmidt <slo...@gmail.com> wrote:
> I have a small companion library that I wrote for model-to-dict
> serialization. I just updated to 1.2.0 and one of my tests is failing --
>
> https://gitlab.com/sloat/SerialAlchemy/blob/master/tests/test_to_dict.py#L193
>
> In 1.1.x, it worked as expected, but in 1.2, the primary-key is added to the
> serialized profile field. So the output is now:
>
> {
>     'firstname': 'test',
>     'profile': {
>         'id': 3,
>         'somefield': 'somevalue'
>         },
> }
>
>
> I just wanted to make sure this is expected behavior from SQLAlchemy. It's
> not a problem for me to update the test, it won't impact the actual
> functionality of the library.

>From making a test (below) I can see this behavior changed within the
1.1 series, not in 1.2. Up through 1.1.13 it gets:

{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at
0x7f8046c5df90>, 'data': u'a'}

in 1.1.14 it becomes:

{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at
0x7f1e0d217e50>, 'data': u'a', 'id': 1}


A bisect brings us to:

https://bitbucket.org/zzzeek/sqlalchemy/issues/4048

this shows there was a bug with undeferral as coming off of a joined
eager load, where the keys to be "undeferred" weren't being acted upon
properly.   pdbing into the example shows that the "id" attribute is
being loaded when load_only() is used, but the bug fixed in 4048 is
preventing the attribute from being populated onto the object
properly.   This implies that the primary key attributes are loaded
even when load_only() seems to exclude them, and that this is the
normally established behavior, here not occurring due to a bug.

This can be confirmed if we change the joinedload to lazyload:

a1 = s.query(A).options(lazyload(A.bs).load_only('data')).one()

print a1.bs[0].__dict__

in an early 1.1 version 1.1.5, we get "id":

{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at
0x7fddb21cffd0>, 'data': u'a', 'id': 1}

therefore the bug fixed in 4048, while it wasn't testing for this
specific condition, is repairing the deferral rules for attributes
coming off of a joinedload, and under that repair the primary key
attributes are now being populated as would be the case when
load_only() is used in other contexts.

This is not to say that the primary key attributes being present under
load_only() is a desirable feature, only that this is how it seems to
have been working overall, and the change here is repairing a bug that
was masking the attribute from completing its population.

On your end I would recommend making your test not depend on the
primary key attributes being there or not so that changes here won't
break your tests.



from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)
    bs = relationship("B")


class B(Base):
    __tablename__ = 'b'
    id = Column(Integer, primary_key=True)
    a_id = Column(ForeignKey('a.id'))
    data = Column(String)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

s = Session(e)

s.add(A(bs=[B(data='a'), B(data='b')]))
s.commit()

a1 = s.query(A).options(joinedload(A.bs).load_only('data')).one()

print a1.bs[0].__dict__









>
> -Matt
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> 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 https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
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 https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to