Masking SAWarning: Flushing object ... with incompatible polymorphic identity

1,444 views
Skip to first unread message

Chris Withers

unread,
Jun 20, 2019, 3:14:06 AM6/20/19
to sqlalchemy
Hi All,

I'm getting this warning:

SAWarning: Flushing object <Cancelled at 0x10b1b9d30> with incompatible
polymorphic identity <Types.done: 'DONE'>; the object may not refresh
and/or load correctly (this warning may be suppressed after 10 occurrences)
    (state_str(state), dict_[polymorphic_key]),

I know why: I'm changing the polymorphic type of a row, but this is
intentional (it's handling a PUT to the entity the row represents) and I
don't believe I'll hit refresh or load problems since once the
transaction is committed, I'm done with the session.

So, two questions:

How can I indicate in my code that this is intentional and no warning
should be omitted?

Why does the following warning filter not work?

warnings.filterwarnings("ignore", category=SADeprecationWarning)
warnings.filterwarnings("ignore", category=SAWarning)

The SADeprecationWarning filter *does* work (and is somewhat legit as
they're coming from a third party library that's awaiting a fix), but
the SAWarning doesn't catch the above.

cheers,

Chris

Mike Bayer

unread,
Jun 20, 2019, 10:40:59 AM6/20/19
to sqlal...@googlegroups.com


On Thu, Jun 20, 2019, at 3:14 AM, Chris Withers wrote:
Hi All,

I'm getting this warning:

SAWarning: Flushing object <Cancelled at 0x10b1b9d30> with incompatible 
polymorphic identity <Types.done: 'DONE'>; the object may not refresh 
and/or load correctly (this warning may be suppressed after 10 occurrences)
    (state_str(state), dict_[polymorphic_key]),

I know why: I'm changing the polymorphic type of a row, but this is 
intentional (it's handling a PUT to the entity the row represents) and I 
don't believe I'll hit refresh or load problems since once the 
transaction is committed, I'm done with the session.

So, two questions:

How can I indicate in my code that this is intentional and no warning 
should be omitted?

you would need to change its class, or replace it with a new object of the correct class.  in both cases you probably need to pull the object out of the Session and put it in again.   if you are making a new object, you would use make_transient_to_detached() to give the object a persistent primary key identity then use session.add() to put it back in again:


if you are doing "obj.__class__ = newclass", you probably need to do the same thing plus more because the identity key needs to have the new class in it, so you could make_transient() to erase the old identity key and then make_transient_to_detached() to give it back a new identity key, then session.add() it.

in both of *those* cases, the history of the object is reset to "clean", so anything you actually want to persist on the object needs to be applied after you've recreated it as a new class with a new identity key.

still another way, that would not reset the history, you can also manipulate state.key directly to have the correct identity key and then replace the object, e.g.

session.expunge(obj)
obj.__class__ = newclass
obj.polymorphic_identity = 'new_identity'
inspect(obj).key = sqlalchemy.orm.identity_key(instance=obj)
session.add(obj)

I'd probably want to make a new object and not change __class__, because changing __class__ in the general case indicates you're going to have an object where its __dict__ can be in an invalid state vs. what the class expects.




Why does the following warning filter not work?

warnings.filterwarnings("ignore", category=SADeprecationWarning)
warnings.filterwarnings("ignore", category=SAWarning)

The SADeprecationWarning filter *does* work (and is somewhat legit as 
they're coming from a third party library that's awaiting a fix), but 
the SAWarning doesn't catch the above.

that is news to me, if that can be demonstrated that should be posted as a new bug.   suspect the _hash_limit_string() aspect that is doing the "suppressed after 10 occurrences" part.



cheers,

Chris

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


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+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Mike Bayer

unread,
Jun 20, 2019, 11:00:54 AM6/20/19
to sqlal...@googlegroups.com
this is not reproducing for me:

from sqlalchemy import util
import warnings
from sqlalchemy import exc

warnings.filterwarnings("ignore", category=exc.SAWarning)

util.warn_limited(
    "Flushing object %s with "
    "incompatible polymorphic identity %r; the "
    "object may not refresh and/or load correctly",
    (object(), 'foo'),
)



with the filter I get no output











cheers,

Chris

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


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+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
 
 
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+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.

Jonathan Vanasco

unread,
Jun 20, 2019, 1:50:02 PM6/20/19
to sqlalchemy


On Thursday, June 20, 2019 at 3:14:06 AM UTC-4, Chris Withers wrote:

How can I indicate in my code that this is intentional and no warning
should be omitted?


Personal option:

I would not mask these.  I would let them persist and probably add a unittest to ensure they are invoked in certain situations.

Masking them runs the risk of masking other SqlAlchemy warnings that you'll want to know about.

I once masked SAWarnings to clear the 'Python2 String in a Unicode Column' warnings.  That resulted in missing a lot of useful SqlAlchemy warnings, which led to the creation of Technical Debt and dedicating a sprint (or two) to critical fixes and upgrades.  Had those warnings not been suppressed, most of the issues would never have manifested because of proper planning. 


Mike Bayer

unread,
Jun 20, 2019, 1:54:29 PM6/20/19
to sqlal...@googlegroups.com
you can omit a specific warning using a regex.   I would at least do that in this case if that's the path chosen.




--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
 
 
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+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.

Chris Withers

unread,
Jun 21, 2019, 2:10:57 AM6/21/19
to sqlal...@googlegroups.com
On 20/06/2019 18:50, Jonathan Vanasco wrote:
>
>
> On Thursday, June 20, 2019 at 3:14:06 AM UTC-4, Chris Withers wrote:
>
>
> How can I indicate in my code that this is intentional and no warning
> should be omitted?
>
>
>
> Personal option:
>
> I would not mask these.  I would let them persist and probably add a
> unittest to ensure they are invoked in certain situations.
>
> Masking them runs the risk of masking other SqlAlchemy warnings that
> you'll want to know about.

Oh, I totally agree, it's more that I couldn't get them to mask *at
all*. Once I got something working I was going to go back to a regex for
just this case, but see other email...

Chris

Chris Withers

unread,
Jun 21, 2019, 2:12:24 AM6/21/19
to sqlal...@googlegroups.com
On 20/06/2019 16:00, Mike Bayer wrote:
>
>
> this is not reproducing for me:
>
> from sqlalchemy import util
> import warnings
> from sqlalchemy import exc
>
> warnings.filterwarnings("ignore", category=exc.SAWarning)
>
> util.warn_limited(
>     "Flushing object %s with "
>     "incompatible polymorphic identity %r; the "
>     "object may not refresh and/or load correctly",
>     (object(), 'foo'),
> )
>
>
>
> with the filter I get no output

Yay! </sarcasm> :-) I hate warn filtering, it never seems to work right
for me, sorry, this is probably a rabbit hole that's not worth worrying
about.

Chris

Chris Withers

unread,
Jun 21, 2019, 2:14:20 AM6/21/19
to sqlal...@googlegroups.com
On 20/06/2019 16:00, Mike Bayer wrote:
>
>> On Thu, Jun 20, 2019, at 3:14 AM, Chris Withers wrote:
>>> Hi All,
>>>
>>> I'm getting this warning:
>>>
>>> SAWarning: Flushing object <Cancelled at 0x10b1b9d30> with incompatible
>>> polymorphic identity <Types.done: 'DONE'>; the object may not refresh
>>> and/or load correctly (this warning may be suppressed after 10
>>> occurrences)
>>>     (state_str(state), dict_[polymorphic_key]),
>>>
Yikes, that escalated quickly.

It probably makes sense just to lose the polymorphic-ness in this case,
I'm not getting enough from it to make the above sensible...

Chris

Mike Bayer

unread,
Jun 21, 2019, 9:08:40 AM6/21/19
to sqlal...@googlegroups.com
something that is changing is likely not a good candidate for polymorphic identity.   That said, you can still have different classes for your "status' if you map the "status" distinctly into a lookup table, and then have your primary object refer to that "status" with a many-to-one relationship.       Or you could use an enumeration class with the Enum datatype.   



Chris

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


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+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages