can you perhaps place a "pdb.set_trace()" inside of session._flush()?
using the debugger you can see the source of every flush() call.
Generally, it occurs each time a query is about to emit SQL.

On Mon, May 7, 2018 at 9:37 PM, Colton Allen <cmanalle...@gmail.com> wrote:
> What exactly causes the session to flush?  I'm trying to track down a nasty
> bug in my versioning system.
>
> Sorry for the long code dump.  I retooled
> examples/versioned_history/history_meta.py so it should look familiar.  The
> function that's breaking is "column_has_changed". I've added some logs as
> well.
>
> # WHEN IT WORKS!
>
> CRITICAL:root:BEFORE MAPPING NEW VALUES
> CRITICAL:root:BEFORE SAVE
> CRITICAL:root:BEFORE REVISE
> CRITICAL:root:CHECK COLUMN CHANGES
> CRITICAL:root:AFTER REVISE
> CRITICAL:root:flush!
> CRITICAL:root:AFTER SAVE
> CRITICAL:root:flush!
>
> # WHEN IT DOESN'T WORK!
>
> CRITICAL:root:BEFORE MAPPING NEW VALUES
> CRITICAL:root:BEFORE SAVE
> CRITICAL:root:BEFORE REVISE
> CRITICAL:root:flush!
> CRITICAL:root:CHECK COLUMN CHANGES
> CRITICAL:root:AFTER REVISE
> CRITICAL:root:AFTER SAVE
> CRITICAL:root:flush!
>
> controller.py
>
> for k, v in dict.items():
>     setattr(model, k, v)
> model.revise()
> db.session.add(model)
> db.session.commit()
>
> model.py
>
> class RevisionMixin:
>     """Version control manager."""
>
>     def revise(self):
>         db.session.add(self)
>         write_revision(self)
>
> version.py
>
> def write_revision(target):
>     target_mapper = orm.object_mapper(target)
>     revision_class = target.__versioned__['model']
>     revision_mapper = revision_class.__mapper__
>
>     object_changed = False
>     state = {}
>
>     for column in iter_mapper_columns(target_mapper, revision_mapper):
>         state[column.key] = getattr(target, column.key)
>         column_changed = column_has_changed(target, column.key)
>         object_changed = object_changed or column_changed
>
>     for relationship, changed in iter_relationships(target, target_mapper):
>         if hasattr(revision_class, relationship.key):
>             state[relationship.key] = getattr(target, relationship.key)
>         object_changed = object_changed or changed
>
>     if not isinstance(target.id, str) or object_changed:
>         _write_revision(target, state)
>
>
> def _write_revision(target, state):
>     version = target.version or 0
>     version = version + 1
>     state['version'] = version
>     state['updated_at'] = db.now()
>     state['primary'] = target
>
>     revision = target.__versioned__['model'](**state)
>     db.session.add(revision)
>
>     target.version = version
>     target.updated_at = state['updated_at']
>
>
> def iter_mapper_columns(primary, revision):
>     mappers = zip(primary.iterate_to_root(), revision.iterate_to_root())
>     for om, hm in mappers:
>         if hm.single:
>             continue
>         for column in iter_shared_columns(om, hm):
>             yield column
>
>
> def iter_shared_columns(mapper, comparison_mapper):
>     for comparison_mapper_column in comparison_mapper.local_table.c:
>         if 'version_meta' in comparison_mapper_column.info:
>             continue
>
>         try:
>             mapper_column =
> mapper.local_table.c[comparison_mapper_column.key]
>             yield mapper.get_property_by_column(mapper_column)
>         except UnmappedColumnError:
>             continue
>
>
> def iter_relationships(target, mapper):
>     for prop in mapper.iterate_properties:
>         if isinstance(prop, RelationshipProperty):
>             passive = attributes.PASSIVE_NO_INITIALIZE
>             changed = attributes.get_history(
>                 target, prop.key, passive=passive).has_changes()
>             yield prop, changed
>
>
> def column_has_changed(target, column_name):
>     # Sometimes the instance state history can't be properly
>     # calculated?  No flushing during versioning.  Unsure why its not
>     # working.
>     added, _, deleted = attributes.get_history(target, column_name)
>     return bool(added or deleted)
>
>
> def relationship_has_changed(prop):
>     for p in prop.local_columns:
>         if p.foreign_keys:
>             return True
>     return False
>
>
> --
> 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