UPDATE: If I inject a session.expunge_all() before I query the DB for the objects again, the "undeclared" attribute is no longer present (i.e. I get the AttributeError I expect).
On Oct 14, 7:08 pm, mviamari <mviam...@gmail.com> wrote: > Michael, > > First, Thanks for your help. > Second, something still isn't right. Here's the code in question: > > obj = Obj() > org = Org() > self.assertNotEqual(obj, None) > self.assertNotEqual(org, None) > > #Nonsense_var is not representative of a table column, > #and is dynamically declared (i.e. not defined in the class > definition). > obj.nonsense_var = 12 > org.nonsense_var = 11 > self.assertEqual(obj.nonsense_var, 12) > self.assertEqual(org.nonsense_var, 11) > > org.obj = obj > > util.database.commit_session() > objid = obj.id > orgid = org.id > > util.database.get_session().expire(obj) > util.database.get_session().expire(org) > > obj = None > org = None > self.assertEqual(obj, None) > self.assertEqual(org, None) > > obj = Obj.get_by(id=objid) > org = Org.get_by(id=orgid) > self.assertNotEqual(obj, None) > self.assertNotEqual(org, None) > > self.assertRaises(AttributeError, getattr, obj, > 'nonsense_var') > self.assertRaises(AttributeError, getattr, org, > 'nonsense_var') > > I don't get the expected AttributeError at the end. Interestingly, if > I delete the org.obj = obj declaration (which is a one-to-one > relationship) it runs as expected. > > The whole point of this is to be able to determine if a given > attribute is part of the object (and corresponding table) definition. > This would be useful, for example, to detect renamed attributes, > deleted attributes, or data transformations when committed to the > database (i.e. 10/11/2009 becomes datatime(2009, 10, 11)). > > Thanks > > Mike > > On Oct 14, 6:44 pm, Michael Bayer <mike...@zzzcomputing.com> wrote: > > > On Oct 14, 2009, at 9:15 PM, mviamari wrote: > > > > So if I read the documentation right, it appears that because I'm > > > accessing the object via the primary key, it looks the object up > > > locally (i.e. in the session) and returns that object. Other than > > > doing a query/lookup on another attribute, how can I force it to > > > create the object from the data in the database? > > > > The key here is that I'd like to be able to verify if an attribute > > > (that corresponds to a DB column) has been deleted. > > > > To complicate matters, I'd also like to be able to do this in a nested > > > transaction, without destroying the session (so I can rollback > > > everything when I'm done). > > > the Session/Query is quite flexible and individual objects can be > > refreshed, expired, etc. as needed. The most direct route is to > > expire() the object in question. Alternatively use the > > populate_existing() method on query which forces a reload. > > > However, if all of this is occuring within a transaction that is > > isolated from others, none of that should be needed - the Session in > > its default settings always synchronizes its state against the current > > transaction automatically, and the object in your identity map does > > represent what's in that transaction - unless you've issued an UPDATE > > or DELETE statement using a plain SQL expression (in which case I'd > > recommend checking out query.update() and query.delete()). After a > > rollback() or commit() when the transaction goes away, all the > > contents of the session are expired so that the new state is loaded > > into the next transaction. > > > > Thanks, > > > > Mike > > > > On Oct 14, 7:00 am, "Michael Bayer" <mike...@zzzcomputing.com> wrote: > > >> mviamari wrote: > > > >>> Hello, > > > >>> I'm writing tests for my database, and I've run into a little bit of > > >>> confusion. > > > >>> Say I have a class (we'll call it person) with two declared > > >>> attributes > > >>> that correspond to db columns: > > > >>> person.id > > >>> person.name > > > >>> If I randomly assign a person object another attribute dynamically: > > > >>> person.undeclared_value = 'New' > > > >>> That value doesn't get stored in the database. (That part I > > >>> expected > > >>> and understand). > > >>> What I don't understand is if I commit the object, set it to None > > >>> (to > > >>> presumably garbage collect it) and then reacquire it from the DB, > > >>> sometimes that dynamically declared attribute is still pesent: > > > >>> person = Person() > > >>> person.name = 'John Smith' > > >>> person.new_attr = 'New' > > > >>> commit() > > >>> id = person.id #id isn't assigned till after a commit > > > >>> person = None > > >>> person = Person.get_by(id=id) > > > >>> #This is expected to be true > > >>> assert person.name = 'John Smith' > > > >>> #This is expected to yield an AttributeError, but sometimes it > > >>> doesn't > > >>> assert person.new_attr = 'New' > > > >>> Based on my tests, it appears that the sometimes it doesn't is > > >>> whenever there are relationships created in the session. If I only > > >>> create one object and follow the above pattern, I get the expected > > >>> results. If I create two objects and the relationship between them, > > >>> then I get the unexpected results. > > > >>> Does anyone have any idea what might be going on? I think the object > > >>> is getting stored in the session, and when I reobtain the object it > > >>> just uses the reference in the session. > > > >> this is the identity map at work. Read "Is the session a cache?" > > >> athttp://www.sqlalchemy.org/docs/05/session.html#frequently-asked-quest > > >> ... > > >> . --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---