Re: [sqlalchemy] history_meta.py: IndexError when creating a new object
Hi Michael, On Monday, 24 August 2015 12:31:20 UTC+10, Michael Bayer wrote: yes and no. Yes, if there's no added history, that should be skipped as you're doing, but no in that that particular line of code is not called if an object is being saved for the first time, only on an update, and then only if that attribute actually had a change, which you are saying this attribute did not. so if you can please share: 1. a mapping and an exact usage that illustrates how this is happening 2. what exact version of SQLAlchemy are you using and 3. have you modified the history_meta.py recipe in any way? Oops, sorry for leaving that out the first time. I'm using SQLAlchemy 1.0.8 on Python 3. I have modified *history_meta.py* for my app, but if I revert the changes the problem is still there. It turns out that the problem happens when the session gets flushed twice. For example: document = Document() self.session.add(document) self.session.flush() document.name = 'Foo' self.session.flush() # IndexError: tuple index out of range In my app I think I need to call flush several times, because I'm building a tree and I need to know the parent IDs. Perhaps I could rearrange my code to not need to do this. Additionally, if I set a different name for a column than the attribute name (as shown below), the value doesn't get propagated to the history table. description_ = Column('description', String, nullable=True) See here for unit tests for both of these issues. It uses an unmodified *history_meta.py*. https://github.com/z0u/satest/blob/master/test_versioned.py Cheers, Alex -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] history_meta.py: IndexError when creating a new object
On 8/24/15 10:15 AM, Alex Fraser wrote: Hi Michael, On Monday, 24 August 2015 12:31:20 UTC+10, Michael Bayer wrote: yes and no. Yes, if there's no added history, that should be skipped as you're doing, but no in that that particular line of code is not called if an object is being saved for the first time, only on an update, and then only if that attribute actually had a change, which you are saying this attribute did not. so if you can please share: 1. a mapping and an exact usage that illustrates how this is happening 2. what exact version of SQLAlchemy are you using and 3. have you modified the history_meta.py recipe in any way? Oops, sorry for leaving that out the first time. I'm using SQLAlchemy 1.0.8 on Python 3. I have modified /history_meta.py/ for my app, but if I revert the changes the problem is still there. It turns out that the problem happens when the session gets flushed twice. For example: | document =Document() self.session.add(document) self.session.flush() document.name ='Foo' self.session.flush() # IndexError: tuple index out of range | In my app I think I need to call flush several times, because I'm building a tree and I need to know the parent IDs. Perhaps I could rearrange my code to not need to do this. Additionally, if I set a different name for a column than the attribute name (as shown below), the value doesn't get propagated to the history table. | description_ =Column('description',String,nullable=True) | See here for unit tests for both of these issues. It uses an unmodified /history_meta.py/. https://github.com/z0u/satest/blob/master/test_versioned.py great, thank you, these issues are both repaired as of d57e5edbcdf915168c613, the diff for his section is: diff --git a/examples/versioned_history/history_meta.py b/examples/versioned_history/history_meta.py index 6d7b137..866f2d4 100644 --- a/examples/versioned_history/history_meta.py +++ b/examples/versioned_history/history_meta.py @@ -210,13 +210,13 @@ def create_version(obj, session, deleted=False): a, u, d = attributes.get_history(obj, prop.key) if d: -attr[hist_col.key] = d[0] +attr[prop.key] = d[0] obj_changed = True elif u: -attr[hist_col.key] = u[0] -else: +attr[prop.key] = u[0] +elif a: # if the attribute had no value. -attr[hist_col.key] = a[0] +attr[prop.key] = a[0] obj_changed = True if not obj_changed: Cheers, Alex -- 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 mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] Is it possible to set the constraint unique = True except for empty string into SQLAlchemy?
If you're using Postgres, you actually wouldn't even need to use a partial index if you can save NULL values instead of empty strings -- a unique constraint would work as intended because Postgres does not compare NULL values to one another. -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] converting date @ hybrid property
After reading more documents i ended up using comparator for my hybrid property instead of expression. like: class JalaliDateComparator(Comparator): def operate(self, op, other): input_date = self.__clause_element__() g_date = other.togregorian() return op(input_date, g_date) So far it seems working, but i'll consider your solution too. i'm not sure which way is best practice but i'm happy that i have two solutions :) Thanks for your reply. On Monday, August 24, 2015 at 7:24:26 AM UTC+4:30, Michael Bayer wrote: On 8/22/15 4:30 PM, Mehdi wrote: Hi I'm using latest sqlalchemy with an Oracle db backend. I have a Date column which presents a *Gregorian date* in db. but i want to query my table by a *Jalali date*. So the hybrid_property to convert gregorian date into jalali date should be like this, i think: @hybrid_property def jalali_date(self): return jdatetime.date.fromgregorian(year=self.input_date.year, month=self.input_date, day=self.input_date.day) i've tried different ways, but all of them ends with errors like: AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with MeasureData.input_date has an attribute 'year' or TypeError: an integer is required (got type InstrumentedAttribute) So i guess i have to get access to *instance value* of *MeasureDate.input_date* at hybrid_property definition, but How? Do i have to completely change my approach? the hybrid allows a Python representation at the object level and a SQL representation at the class level. Your error message involves the term InstrumentedAttribute, which suggests you are attempting to use this hybrid at the class level (please provide full stack traces to make this clearer). Your hybrid as defined only illustrates instance-level conversions and there's not a simple way to do this conversion at the SQL level especially in Oracle, unless you had some stored procedure which does so. Therefore, you are probably looking for an in-Python value of a Jalali date to be converted from the alternate calendar to the gregorian (SQL-persisted) calendar *in python*, before it is sent to the database, and converted back to Jalali *in Python* after being received from the database as a result. For this, you want to build a custom type similar to the MyEpochType illustrated at http://docs.sqlalchemy.org/en/rel_1_0/core/custom_types.html#augmenting-existing-types - using this type will cause expressions like equality comparisons to coerce the value side of the expression, e.g. the raw datetime object, as according to your rules. You can then cause this particular type to be used with your hybrid using type_coerce.Here's an example using most features of hybrids: from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.hybrid import hybrid_property import jdatetime import datetime Base = declarative_base() class JDate(TypeDecorator): impl = Date def process_bind_param(self, value, dialect): if value is not None: value = jdatetime.date.togregorian(value) return value def process_result_value(self, value, dialect): if value is not None: value = jdatetime.date.fromgregorian( year=value.year, month=value.month, day=value.day) return value class A(Base): __tablename__ = 'a' id = Column(Integer, primary_key=True) input_date = Column(Date) @hybrid_property def jalali_date(self): return jdatetime.date.fromgregorian( year=self.input_date.year, month=self.input_date.month, day=self.input_date.day) @jalali_date.expression def jalali_date(cls): return type_coerce(cls.input_date, JDate) @jalali_date.setter def jalali_date(self, value): self.input_date = jdatetime.date.togregorian(value) e = create_engine(postgresql://scott:tiger@localhost/test, echo=True) Base.metadata.drop_all(e) Base.metadata.create_all(e) a1 = A(jalali_date=jdatetime.date(1380, 8, 2)) a2 = A(input_date=datetime.date(2001, 10, 24)) s = Session(e) s.add_all([a1, a2]) s.commit() s.close() a1, a2 = s.query(A).filter_by(jalali_date=jdatetime.date(1380, 8, 2)).all() print a1.jalali_date, a2.jalali_date print a1.input_date, a2.input_date in the output, we can see that jalali_date and input_date are consistent from both ways of setting, both ways of matching: 1380-08-02 1380-08-02 2001-10-24 2001-10-24 Thanks. -- 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
Re: [sqlalchemy] history_meta.py: IndexError when creating a new object
Hi Mike, On Tuesday, 25 August 2015 00:56:03 UTC+10, Michael Bayer wrote: great, thank you, these issues are both repaired as of d57e5edbcdf915168c613, the diff for his section is: Thanks very much! That works perfectly. By the way, you asked if I had changed *history_meta.py* at all: I added some properties on *Versioned* to allow conditional versioning: --- src/app/server/history_meta_orig.py 2015-08-25 10:21:57.555888454 +1000 +++ src/app/server/history_meta.py 2015-08-25 10:23:08.342461090 +1000 @@ -157,6 +157,28 @@ return mp return map +@property +def version_on_update(self): +try: +return self._version_on_update +except AttributeError: +return True + +@version_on_update.setter +def version_on_update(self, enabled): +self._version_on_update = enabled + +@property +def version_on_delete(self): +try: +return self._version_on_delete +except AttributeError: +return True + +@version_on_delete.setter +def version_on_delete(self, enabled): +self._version_on_delete = enabled + def versioned_objects(iter): for obj in iter: @@ -249,7 +271,8 @@ @event.listens_for(session, 'before_flush') def before_flush(session, flush_context, instances): for obj in versioned_objects(session.dirty): -create_version(obj, session) +if obj.version_on_update: +create_version(obj, session) for obj in versioned_objects(session.deleted): -create_version(obj, session, deleted=True) - +if obj.version_on_delete: +create_version(obj, session, deleted=True) The use case being that I only want to create a new version if the user saving an object is different from the user who last saved it. I also thought about adding an explicit *Versioned.create_version* method, but this suffices for now. Cheers, Alex -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] history_meta.py: foreign keys in history table, and relationships
Hi Mike, Thanks for your help with my other problem. I have a couple of other questions / a wishlist: Is there a declarative way to add foreign keys to the history table when using history_meta.py? In the app I'm making the user can view old versions of a document, and I want to make sure e.g. the user that created the old version can't be deleted while their old versions exist. Finally, it would be nice if other attributes could be carried over to the history mapper. If they had a similar API, the history objects could be worked with (e.g. serialised to JSON) in the same way as the non-history objects. Perhaps this could be done by carrying over methods decorated with @declared_attr? Something like this (untested): def test_history_relationships(self): class User(self.Base): __tablename__ = 'appuser' id = Column(Integer, primary_key=True) name = Column(String) class Document(Versioned, self.Base): __tablename__ = 'document' id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey(appuser.id)) contents = Column(String) @declared_attr def user(cls): return relationship(AppUser) self.create_tables() user = User(name=Fred) self.session.flush() document = Document(user_id=user.id) document.contents = foo self.session.flush() document.contents = bar self.session.flush() DocumentHistory = Document.__history_mapper__.class_ v2 = self.session.query(Document).one() v1 = self.session.query(DocumentHistory).one() self.assertEqual(v2.user.name, Fred) self.assertTrue(hasattr(v1, 'user')) self.assertEqual(v1.user.name, Fred) Although it would be nice if it worked with other attributes too, such as hybrid properties. Maybe they would need to be specially decorated for use only by the history mapper, so that relationships weren't made bidirectional. Currently I'm doing this by manually querying the related tables - but I feel this is prone to error, because code for doing the join is duplicated. E.g. instead of doing *user_name = v1.user.name*, I do: user = self.session.query(User).filter_by(id=v1.user_id).one() user_name = user.name I feel like I'm doing something wrong; any suggestions for improving this would be appreciated. Cheers, Alex SQLAlchemy 1.0.8, Python 3, PostgreSQL 9.4 -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] mapper_configured event, class fully configured?
Hi again, I'm trying to track an issue making use of Marshmallow-SQLAlchemy (I've also seen what looks like a very similar problem in ColanderAlchemy, but I haven't dug into that yet). I think it might have something to do with the mapper_configured event and whether the class is truly fully configured at that point. Possibly I'm misunderstanding what that means. If I do something like this: import sqlalchemy as sa from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session, sessionmaker, relationship from sqlalchemy import event from sqlalchemy.orm import mapper engine = sa.create_engine('sqlite:///:memory:') session = scoped_session(sessionmaker(bind=engine)) Base = declarative_base() class Author(Base): __tablename__ = 'authors' id = sa.Column(sa.Integer, primary_key=True) name = sa.Column(sa.String) def __repr__(self): return 'Author(name={self.name!r})'.format(self=self) class Book(Base): __tablename__ = 'books' id = sa.Column(sa.Integer, primary_key=True) title = sa.Column(sa.String) author_id = sa.Column(sa.Integer, sa.ForeignKey('authors.id')) author = relationship(Author, backref='books') def __repr__(self): return 'Book(title={self.title!r})'.format(self=self) Base.metadata.create_all(engine) def print_stuff(mapper, class_): print getattr(class_, 'books') event.listen(mapper, 'mapper_configured', print_stuff) author = Author(name='Chuck Paluhniuk') When I run this code, the result is that when Author is first used, the 'mapper_configured' event will fire and my print_stuff function callback will run. The results is this: Traceback (most recent call last): File marshmallow_experiment.py, line 37, in module author = Author(name='Chuck Paluhniuk') File string, line 2, in __init__ File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py, line 347, in _new_state_if_none state = self._state_constructor(instance, self) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py, line 747, in __get__ obj.__dict__[self.__name__] = result = self.fget(obj) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py, line 177, in _state_constructor self.dispatch.first_init(self, self.class_) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py, line 258, in __call__ fn(*args, **kw) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py, line 2792, in _event_on_first_init configure_mappers() File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py, line 2691, in configure_mappers mapper, mapper.class_) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py, line 218, in __call__ fn(*args, **kw) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/events.py, line 527, in wrap fn(*arg, **kw) File marshmallow_experiment.py, line 33, in print_stuff print getattr(class_, 'books') AttributeError: type object 'Author' has no attribute 'books' Should not the backref be configured at that point? What I'm trying to do is use the mapper_configured event in order to autocreate marshamallow-sqlalchemy schemas, which works fine except that because books doesn't exist at the point when the callback function runs, the resulting schema is also missing the books part. If I do this instead: author = Author(name='Chuck Paluhniuk') print_stuff(None, Author) Then the result is: Author.books I.e. It is now there. Thanks again for your continued excellent support. Douglas -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] mapper_configured event, class fully configured?
On 8/24/15 9:21 PM, Mike Bayer wrote: On 8/24/15 7:41 PM, Douglas Russell wrote: | def print_stuff(mapper, class_): print getattr(class_, 'books') event.listen(mapper, 'mapper_configured', print_stuff) author = Author(name='Chuck Paluhniuk') | When I run this code, the result is that when Author is first used, the 'mapper_configured' event will fire and my print_stuff function callback will run. The results is this: | Traceback (most recent call last): File marshmallow_experiment.py, line 37, in module author = Author(name='Chuck Paluhniuk') File string, line 2, in __init__ File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py, line 347, in _new_state_if_none state = self._state_constructor(instance, self) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py, line 747, in __get__ obj.__dict__[self.__name__] = result = self.fget(obj) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py, line 177, in _state_constructor self.dispatch.first_init(self, self.class_) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py, line 258, in __call__ fn(*args, **kw) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py, line 2792, in _event_on_first_init configure_mappers() File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py, line 2691, in configure_mappers mapper, mapper.class_) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py, line 218, in __call__ fn(*args, **kw) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/events.py, line 527, in wrap fn(*arg, **kw) File marshmallow_experiment.py, line 33, in print_stuff print getattr(class_, 'books') AttributeError: type object 'Author' has no attribute 'books' | Should not the backref be configured at that point? What I'm trying to do is use the mapper_configured event in order to autocreate marshamallow-sqlalchemy schemas, which works fine except that because books doesn't exist at the point when the callback function runs, the resulting schema is also missing the books part. If I do this instead: | author = Author(name='Chuck Paluhniuk') print_stuff(None, Author) | Then the result is: | Author.books | so you can see what's happening here. Author.books is being set up, but not within the event. In this case Author is being configured before Book, and as far as it knows, that's it, it's done. The event is called. Book hasn't been touched so therefore neither has books. Only outside of the whole thing, where Book also got set up, does your inspection work. The solution is to either use back_populates instead of backref, which is probably the only way the ORM would have done it today if starting again, or use the after_configured() event http://docs.sqlalchemy.org/en/rel_1_0/orm/events.html#sqlalchemy.orm.events.MapperEvents.after_configured which is intentionally here so that you can do things that require all known mappers to be fully set up, which is the case here. As is so often the case I'm horrified the API docs don't have cross linking here. doing that.. I've pushed up new descriptions and full cross-linking between configure_mappers(), mapper_configured(), before_configured() and after_configured(), for 0.9, 1.0, 1.1, master. Should be up on the site in a little while. -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] mapper_configured event, class fully configured?
On 8/24/15 7:41 PM, Douglas Russell wrote: | def print_stuff(mapper, class_): print getattr(class_, 'books') event.listen(mapper, 'mapper_configured', print_stuff) author = Author(name='Chuck Paluhniuk') | When I run this code, the result is that when Author is first used, the 'mapper_configured' event will fire and my print_stuff function callback will run. The results is this: | Traceback (most recent call last): File marshmallow_experiment.py, line 37, in module author = Author(name='Chuck Paluhniuk') File string, line 2, in __init__ File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py, line 347, in _new_state_if_none state = self._state_constructor(instance, self) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py, line 747, in __get__ obj.__dict__[self.__name__] = result = self.fget(obj) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py, line 177, in _state_constructor self.dispatch.first_init(self, self.class_) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py, line 258, in __call__ fn(*args, **kw) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py, line 2792, in _event_on_first_init configure_mappers() File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py, line 2691, in configure_mappers mapper, mapper.class_) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/event/attr.py, line 218, in __call__ fn(*args, **kw) File /usr/local/Cellar/python/2.7.10/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sqlalchemy/orm/events.py, line 527, in wrap fn(*arg, **kw) File marshmallow_experiment.py, line 33, in print_stuff print getattr(class_, 'books') AttributeError: type object 'Author' has no attribute 'books' | Should not the backref be configured at that point? What I'm trying to do is use the mapper_configured event in order to autocreate marshamallow-sqlalchemy schemas, which works fine except that because books doesn't exist at the point when the callback function runs, the resulting schema is also missing the books part. If I do this instead: | author = Author(name='Chuck Paluhniuk') print_stuff(None, Author) | Then the result is: | Author.books | so you can see what's happening here. Author.books is being set up, but not within the event. In this case Author is being configured before Book, and as far as it knows, that's it, it's done. The event is called. Book hasn't been touched so therefore neither has books. Only outside of the whole thing, where Book also got set up, does your inspection work. The solution is to either use back_populates instead of backref, which is probably the only way the ORM would have done it today if starting again, or use the after_configured() event http://docs.sqlalchemy.org/en/rel_1_0/orm/events.html#sqlalchemy.orm.events.MapperEvents.after_configured which is intentionally here so that you can do things that require all known mappers to be fully set up, which is the case here. As is so often the case I'm horrified the API docs don't have cross linking here. doing that.. I.e. It is now there. Thanks again for your continued excellent support. Douglas -- 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 mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.