I think I did it right.  The logs just didn't scroll up.  This might be 
causing the issue (account is a orm.relationship).

api_1     |   File "/app/models/post/__init__.py", line 160, in 
manage_review_status
api_1     |     if not target.account.settings.compliance_enable_post:



Full logs:

api_1     | Traceback (most recent call last):
api_1     |   File "/usr/local/lib/python3.5/site-packages/werkzeug/wsgi.py"
, line 660, in __call__
api_1     |     return app(environ, start_response)
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 2000, in __call__
api_1     |     return self.wsgi_app(environ, start_response)
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1988, in wsgi_app
api_1     |     response = self.full_dispatch_request()
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/flask_cors/extension.py", line 161, 
in wrapped_function
api_1     |     return cors_after_request(app.make_response(f(*args, **
kwargs)))
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1567, in handle_exception
api_1     |     reraise(exc_type, exc_value, tb)
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/_compat.py"
, line 33, in reraise
api_1     |     raise value
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1988, in wsgi_app
api_1     |     response = self.full_dispatch_request()
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1639, in full_dispatch_request
api_1     |     rv = self.dispatch_request()
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/flask_cors/extension.py", line 161, 
in wrapped_function
api_1     |     return cors_after_request(app.make_response(f(*args, **
kwargs)))
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1544, in handle_user_exception
api_1     |     reraise(exc_type, exc_value, tb)
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/_compat.py"
, line 33, in reraise
api_1     |     raise value
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1639, in full_dispatch_request
api_1     |     rv = self.dispatch_request()
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", 
line 1625, in dispatch_request
api_1     |     return self.view_functions[rule.endpoint](**req.view_args)
api_1     |   File "/app/common/errors.py", line 67, in decorator
api_1     |     return fn(*args, **kwargs)
api_1     |   File "/app/common/auth.py", line 295, in decorator
api_1     |     return fn(*args, **kwargs)
api_1     |   File "/app/common/auth.py", line 303, in decorator
api_1     |     return fn(*args, **kwargs)
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/flask_principal.py", line 199, in 
_decorated
api_1     |     rv = f(*args, **kw)
api_1     |   File "/usr/local/lib/python3.5/site-packages/flask/views.py", 
line 84, in view
api_1     |     return self.dispatch_request(*args, **kwargs)
api_1     |   File "/app/common/resource.py", line 104, in dispatch_request
api_1     |     return action(*args, **kwargs)
api_1     |   File "/app/api/account/resources/pages/__init__.py", line 66, 
in patch
api_1     |     model = self.save(model)
api_1     |   File "/app/api/account/resources/pages/__init__.py", line 84, 
in save
api_1     |     model.revise()
api_1     |   File "/app/common/revision.py", line 77, in revise
api_1     |     execute_preprocessors(self)
api_1     |   File "/app/common/revision.py", line 84, in 
execute_preprocessors
api_1     |     processor(target)
api_1     |   File "/app/models/post/__init__.py", line 160, in 
manage_review_status
api_1     |     if not target.account.settings.compliance_enable_post:
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py", line 
237, in __get__
api_1     |     return self.impl.get(instance_state(instance), dict_)
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py", line 
584, in get
api_1     |     value = self.callable_(state, passive)
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/strategies.py", line 
557, in _load_for_state
api_1     |     return self._emit_lazyload(session, state, ident_key, 
passive)
api_1     |   File "<string>", line 1, in <lambda>
api_1     |     
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/strategies.py", line 
635, in _emit_lazyload
api_1     |     result = q.all()
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2703, 
in all
api_1     |     return list(self)
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/query.py", line 2854, 
in __iter__
api_1     |     self.session._autoflush()
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/session.py", line 
1365, in _autoflush
api_1     |     self.flush()
api_1     |   File 
"/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/session.py", line 
2139, in flush
api_1     |     self._flush(objects)
api_1     |   File "/app/common/sqlalchemy.py", line 17, in _flush
api_1     |     super()._flush(objects)
api_1     |   File "/app/common/sqlalchemy.py", line 17, in _flush
api_1     |     super()._flush(objects)
api_1     |   File "/usr/local/lib/python3.5/bdb.py", line 48, in 
trace_dispatch
api_1     |     return self.dispatch_line(frame)
api_1     |   File "/usr/local/lib/python3.5/bdb.py", line 67, in 
dispatch_line
api_1     |     if self.quitting: raise BdbQuit
api_1     | bdb.BdbQuit



On Monday, May 7, 2018 at 7:27:03 PM UTC-7, Mike Bayer wrote:
>
> 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 <cmana...@gmail.com 
> <javascript:>> 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+...@googlegroups.com <javascript:>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:>. 
> > 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