Re: [sqlalchemy] Connection pooling strategy for a small/fixed number of db users

2015-03-03 Thread Russ


 well the engine is essentially a holder for a connection pool. If you use 
 a 
 pool like NullPool, it makes a new connection on every use, but in that 
 case 
 there is still not an official way to send in different connection 
 parameters. There’s no advantage to trying to make Engine work in a 
 different way, using two engines is just shorthand for using two different 
 sets of credentials. 


Ok.  That makes sense.  Thanks for clarifying.

Definitely don’t need two sessionmakers, the engine can be passed both to 
 the constructor of Session directly as well as to the sessionmaker 
 function 
 at the moment the new Session is created. But it shouldn’t be any less 
 convenient to have two sessionmakers vs. passing two different engines in, 
 vs. passing connection credentials in somewhere when you need to connect. 
 There’s “two of something” going on no matter how you try to organize 
 that. 


So I only need to select the relevant engine and pas to my )scoped) 
sessionmaker, then.  Great.
 

 I think what’s odd here is that if this is a web app, why is it needing to 
 maintain two sets of credentials internally in a single process for what 
 is 
 apparently the same database. 


Some of the functions in the API allow arbitrary SQL strings to be passed 
for execution... but restricted access/views for reporting only.  The API 
path is used to control server access, rather than exposing the database 
(postgres) to direct external connections.  Postgres only listens on 
localhost.  The implementation for these APIs then uses separate 
credentials to ensure read-only access in their implementation, whereas the 
vast majority of APIs have full access.

Still odd? :)

Thanks for the help, guys!

Russ

-- 
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] Unicode String Error on Insert

2015-03-03 Thread J.D.
Hi,

I am getting the following error, when I try to execute code to insert a 
new row into one of my tables, and I've googled for answers and tried 
everything I could find online and nothing seems to resolve the issue.

sqlalchemy.exc.ProgrammingError: (ProgrammingError) You must not use 8-bit 
bytestrings unless you use a text_factory that can interpret 8-bit 
bytestrings (like text_factory = str)

*I am using the following software:*

SQLAlchemy v0.9.8

SQLite 3.8.8.2.

*I am creating my engine as follows,*

engine = create_engine('sqlite+pysqlite:///prototype.db', module=sqlite)

#engine.raw_connection().connection.text_factory = str

#engine.connect().connection.connection.text_factory = str

session = sessionmaker(bind=engine)()

meta.Base.metadata.bind = engine

meta.Base.metadata.create_all(engine)

*The object I am trying to insert via session.add(..) has a structure 
similar to the following: (shortened for brevity)*

..

id = Column(Integer, primary_key=True, unique=True, nullable=False)

title = Column(String, nullable=False) // This is the column that 
gets the Portuguese data with unicode characters -- I've tried using the 
column type Unicode

# title = Column(Unicode, nullable=False)

book_id = Column(Integer, nullable=False)

code = Column(Integer, nullable=False)

...

*I've tried setting the text_factory on the connection to no avail.  I'm at 
a loss how to fix this so I can insert my data with unicode chars.*

Here is the SQL that is generated for the insert

It is highly recommended that you instead just switch your application to 
Unicode strings. u'INSERT INTO books (title, book_id, code) VALUES (?, ?, 
?)' ('Demana/Blitzer: Pr\x8e-c\x87lculo, 2e', '93810', 'removed')

I would appreciate some insight to how to fix this issue so I can insert my 
data.

Thanks,

J.D.




-- 
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] Relationship behavior change when switching from reflected to declarative styles; test case included

2015-03-03 Thread Evan James
Hi folks,

I'm working on a SQLAlchemy-based app where we've decided to make some 
infrastructure changes, in particular moving from reflection to declaration 
for mapping the models.

However, we're now running into issues where, after switching to 
declarative, relationships aren't populated the way we expect when 
manipulated in Python.  For example, we have code that looks like this:

class Widget(...):
def merge(self, other_widget):
Merge the widgets, transferring the dependent items on the other 
widget to this one.
for frobnicator in other_widget.frobnicators[:]:
frobnicator.widget = self

meta.Session.delete(other_widget)


This code worked as hoped-for when we were reflecting on the database to 
create our mappers, but after switching to declarative, the dependent items 
are cascade-deleted on commit when other_widget is deleted, rather than 
being preserved as children of the merged widget.

It's not difficult to fix this particular issue - explicitly removing the 
frobnicators from the other_widget.frobnicators collection will prevent 
them from being deleted, and then the merged widget correctly has them - 
but we're finding we have a class of bugs where relationships aren't being 
handled the same way as before.  Unfortunately, build a comprehensive test 
suite is one of the infrastructure changes we're in the process of making 
- which means it's not done yet and we can't easily track down all the 
places we could get tripped up.  We would really prefer to resolve this by 
changing the definitions in the models, not by changing the application 
code that manipulates the membership of relationships.

I've created a reduced test case here 
https://github.com/ejames/sqlalchemy_reflection_problem_reduction which 
specifically displays the behavior we're having trouble with in minimal 
form.  If one line in the test case is commented out, the test will pass 
for reflective models and fail for declarative models; if the line is put 
back in, success and failure reverse.

My question:  How can we make relationships function identically in 
declarative syntax as they did in reflective syntax?  We thought we had 
migrated mapping styles in a way that wouldn't change anything, but here we 
are.  What are we missing?

Thanks,
Evan James

-- 
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] Re: Unicode String Error on Insert

2015-03-03 Thread J.D.
My solution didn't work.  I was able to get my Portuguese data to load by 
decoding it in ISO-8859-1, but by decoding I lose all the special 
characters like tildes.

So I still don't understand how to get the engine to accept my data 
properly.

J.D.

On Tuesday, March 3, 2015 at 3:00:24 PM UTC-7, J.D. wrote:

 I actually figured this out.

 It had nothing to do with my SQLAlchemy create_engine configuration.

 The data I was trying to create an object with was in ISO-8859-1 format, 
 so I just had to construct my Object the text decoded properly.

 Once I did this, the data was inserted into my sqlite3 table just fine.


 On Tuesday, March 3, 2015 at 1:58:32 PM UTC-7, J.D. wrote:

 Hi,

 I am getting the following error, when I try to execute code to insert a 
 new row into one of my tables, and I've googled for answers and tried 
 everything I could find online and nothing seems to resolve the issue.

 sqlalchemy.exc.ProgrammingError: (ProgrammingError) You must not use 
 8-bit bytestrings unless you use a text_factory that can interpret 8-bit 
 bytestrings (like text_factory = str)

 *I am using the following software:*

 SQLAlchemy v0.9.8

 SQLite 3.8.8.2.

 *I am creating my engine as follows,*

 engine = create_engine('sqlite+pysqlite:///prototype.db', module=sqlite)

 #engine.raw_connection().connection.text_factory = str

 #engine.connect().connection.connection.text_factory = str

 session = sessionmaker(bind=engine)()

 meta.Base.metadata.bind = engine

 meta.Base.metadata.create_all(engine)

 *The object I am trying to insert via session.add(..) has a structure 
 similar to the following: (shortened for brevity)*

 ..

 id = Column(Integer, primary_key=True, unique=True, nullable=False)

 title = Column(String, nullable=False) // This is the column 
 that gets the Portuguese data with unicode characters -- I've tried using 
 the column type Unicode

 # title = Column(Unicode, nullable=False)

 book_id = Column(Integer, nullable=False)

 code = Column(Integer, nullable=False)

 ...

 *I've tried setting the text_factory on the connection to no avail.  I'm 
 at a loss how to fix this so I can insert my data with unicode chars.*

 Here is the SQL that is generated for the insert

 It is highly recommended that you instead just switch your application to 
 Unicode strings. u'INSERT INTO books (title, book_id, code) VALUES (?, ?, 
 ?)' ('Demana/Blitzer: Pr\x8e-c\x87lculo, 2e', '93810', 'removed')

 I would appreciate some insight to how to fix this issue so I can insert 
 my data.

 Thanks,

 J.D.






-- 
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] Relationship behavior change when switching from reflected to declarative styles; test case included

2015-03-03 Thread Michael Bayer


Evan James thas...@gmail.com wrote:

 Hi folks,
 
 I'm working on a SQLAlchemy-based app where we've decided to make some 
 infrastructure changes, in particular moving from reflection to declaration 
 for mapping the models.
 
 However, we're now running into issues where, after switching to declarative, 
 relationships aren't populated the way we expect when manipulated in Python.  
 For example, we have code that looks like this:
 
 class Widget(...):
 def merge(self, other_widget):
 Merge the widgets, transferring the dependent items on the other 
 widget to this one.
 for frobnicator in other_widget.frobnicators[:]:
 frobnicator.widget = self
 
 meta.Session.delete(other_widget)
 
 
 This code worked as hoped-for when we were reflecting on the database to 
 create our mappers, but after switching to declarative, the dependent items 
 are cascade-deleted on commit when other_widget is deleted, rather than being 
 preserved as children of the merged widget.
 
 It's not difficult to fix this particular issue - explicitly removing the 
 frobnicators from the other_widget.frobnicators collection will prevent them 
 from being deleted, and then the merged widget correctly has them - but we're 
 finding we have a class of bugs where relationships aren't being handled the 
 same way as before.  Unfortunately, build a comprehensive test suite is one 
 of the infrastructure changes we're in the process of making - which means 
 it's not done yet and we can't easily track down all the places we could get 
 tripped up.  We would really prefer to resolve this by changing the 
 definitions in the models, not by changing the application code that 
 manipulates the membership of relationships.


Essentially the issue is likely because the mappings in these two examples
are not equivalent; the reflection based version has Widget.frobnicator and
Frobnicator.widget communicating with each other through a backref, and the
declarative version does not.

Assuming you’re on SQLA 0.9, the reflective version is taking advantage of
the behavior introduced in
http://docs.sqlalchemy.org/en/rel_0_9/changelog/migration_09.html#backref-handlers-can-now-propagate-more-than-one-level-deep;
that is, adding frobnicator to first_widget.frobincators affects the backref
of frobnicator.widget which then automatically performs the remove of
second_widget.frobnicators. The declarative version does not make any use of
the “backref” or “back_populates” keyword so cannot take advantage of this
behavior; it doesn’t track any linkage between these two sides.

The section
http://docs.sqlalchemy.org/en/rel_0_9/orm/backref.html?highlight=backref
talks about how to configure either backref or back_populates between
mutually-dependent relationships.



 I've created a reduced test case here which specifically displays the 
 behavior we're having trouble with in minimal form.  If one line in the test 
 case is commented out, the test will pass for reflective models and fail for 
 declarative models; if the line is put back in, success and failure reverse.
 
 My question:  How can we make relationships function identically in 
 declarative syntax as they did in reflective syntax?  We thought we had 
 migrated mapping styles in a way that wouldn't change anything, but here we 
 are.  What are we missing?
 
 Thanks,
 Evan James
 
 -- 
 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.

-- 
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] Re: Unicode String Error on Insert

2015-03-03 Thread J.D.
I actually figured this out.

It had nothing to do with my SQLAlchemy create_engine configuration.

The data I was trying to create an object with was in ISO-8859-1 format, so 
I just had to construct my Object the text decoded properly.

Once I did this, the data was inserted into my sqlite3 table just fine.


On Tuesday, March 3, 2015 at 1:58:32 PM UTC-7, J.D. wrote:

 Hi,

 I am getting the following error, when I try to execute code to insert a 
 new row into one of my tables, and I've googled for answers and tried 
 everything I could find online and nothing seems to resolve the issue.

 sqlalchemy.exc.ProgrammingError: (ProgrammingError) You must not use 8-bit 
 bytestrings unless you use a text_factory that can interpret 8-bit 
 bytestrings (like text_factory = str)

 *I am using the following software:*

 SQLAlchemy v0.9.8

 SQLite 3.8.8.2.

 *I am creating my engine as follows,*

 engine = create_engine('sqlite+pysqlite:///prototype.db', module=sqlite)

 #engine.raw_connection().connection.text_factory = str

 #engine.connect().connection.connection.text_factory = str

 session = sessionmaker(bind=engine)()

 meta.Base.metadata.bind = engine

 meta.Base.metadata.create_all(engine)

 *The object I am trying to insert via session.add(..) has a structure 
 similar to the following: (shortened for brevity)*

 ..

 id = Column(Integer, primary_key=True, unique=True, nullable=False)

 title = Column(String, nullable=False) // This is the column that 
 gets the Portuguese data with unicode characters -- I've tried using the 
 column type Unicode

 # title = Column(Unicode, nullable=False)

 book_id = Column(Integer, nullable=False)

 code = Column(Integer, nullable=False)

 ...

 *I've tried setting the text_factory on the connection to no avail.  I'm 
 at a loss how to fix this so I can insert my data with unicode chars.*

 Here is the SQL that is generated for the insert

 It is highly recommended that you instead just switch your application to 
 Unicode strings. u'INSERT INTO books (title, book_id, code) VALUES (?, ?, 
 ?)' ('Demana/Blitzer: Pr\x8e-c\x87lculo, 2e', '93810', 'removed')

 I would appreciate some insight to how to fix this issue so I can insert 
 my data.

 Thanks,

 J.D.






-- 
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] Re: Flushed PickleType data disappearing

2015-03-03 Thread SQLRook
To move one step from your sample toward my codebase, I made a class method 
to modify the pickled list.  Already, I see behavior that I cannot 
explain.  If the session is passed to modifyTarget(), you can observe the 
targetInstance become dirty, marked as modified, and then by the end of the 
function, the column is no longer modified, even though the contents have 
changed twice.  How does a column become un-modified? (for scalar values, I 
understand that an int column would in net not be modified if its value 
changed from 6 to 10 to 6).  You can optionally not pass the session to 
modifyTarget(), and the object won't be modified after the call.

class Target(Base):
__tablename__ = 'targets'
id = Column(Integer, primary_key=True)
name = Column(Unicode)
targetList = Column(PickleType, default=[])

def modifyTarget(self,dbSession=None):
print 'target list on entry: ' + str(self.targetList)
if dbSession:
assert not any(dbSession.dirty)
print 'modified on entry? ' + str(dbSession.is_modified(self))
temp = self.targetList
self.targetList = None
if dbSession:
assert any(dbSession.dirty)
assert dbSession.is_modified(self)
temp.append(6)
if dbSession:
assert any(dbSession.dirty)
print 'session dirty objs: ' + str(dbSession.dirty)
self.targetList, temp = temp, self.targetList#swap
print 'target list on exit: ' + str(self.targetList) 
if dbSession:
assert dbSession.is_modified(self)


def run(dbSession):
targetInstance = Target(name='t1', targetList=[1, 2, 3])
dbSession.add(targetInstance)
dbSession.flush()

targetInstance.modifyTarget()#pass dbSession if you like
assert dbSession.is_modified(targetInstance)
assert any (dbSession.dirty)
print 'begin flush 2...'
dbSession.flush()

assert not any(dbSession.dirty)
assert not dbSession.is_modified(targetInstance)


e = create_engine(sqlite://, echo=True)
Base.metadata.create_all(e)

s = Session(e)
run(s)
s.commit()

s = Session(e)
assert s.query(Target.targetList).scalar() == [4, 5, 6]
print 'done.'

One additional way in which my codebase differs from the sample is that the 
list contents are instances of a user-defined class, which itself inherits 
from declarative base.  That may be an extraneous detail if something odd 
is already happening, though.




On Thursday, February 26, 2015 at 4:14:22 PM UTC-5, SQLRook wrote:

 I'm having an issue where a list of user-defined objects is disappearing 
 as a function goes out of scope.  The list is stored in a PickleType 
 column, and as that type does not track changes in the objects of the list, 
 I am (knowingly, inefficiently) forcing the column to become dirty by 
 setting the corresponding Python object to an empty list, and then to the 
 new list value.  This is Python 2.7.3 with SQLAlchemy 0.9.8.  The session 
 I'm using in the following code is created from a sessionmaker with default 
 values aside form *expire_on_commit*, which is False.

 The declaration of the class containing the list is simplified to the 
 following:

 class Target:
 __tablename__ = 'targets'
 id = Column(Integer, primary_key=True)
 name = Column(Unicode)
 targetList = Column(PickleType, default=[])


 def run(dbSession):
 targetInstance = makeTI(dbSession)#adds instance to session, flushes
 modifyList(targetInstance, dbSession, data)#blinks list values, 
 dirties object in session.  Flushes changes, and all list contents are 
 still subsequently present
 assert not any(dbSession.dirty)#assert passes
 assert not dbSession.is_modified(targetInstance)#assert passes
 print 'targetInstance list contents after init: ' + 
 str(targetInstance.targetList)#prints list contents as expected
 #last place list contents are present. Upon return of run(), list will 
 be empty again
 return

 After flow of control returns to the caller of run(), a commit is done, 
 then targetInstance is queried from the session, and the list is empty.  
 Even if the list is accessed, or explicitly refreshed from the session, the 
 list is empty.  How is that possible if the once-dirty session was flushed?

 I know that there is optional in-place mutation tracking, but that's not 
 being used here.
 The relevant links are the official 
 http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/mutable.html 
 mutable docs, an extended conversation 
 https://bitbucket.org/zzzeek/sqlalchemy/issue/2994/pickletype-gets-not-updated-in-database-in
  
 with Mike on BitBucket.


-- 
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 

Re: [sqlalchemy] Unicode String Error on Insert

2015-03-03 Thread Michael Bayer

J.D. jd.cor...@pearson.com wrote:

 My solution didn't work.  I was able to get my Portuguese data to load by 
 decoding it in ISO-8859-1, but by decoding I lose all the special characters 
 like tildes.
 
 So I still don't understand how to get the engine to accept my data properly.
 
 J.D.
 
 On Tuesday, March 3, 2015 at 3:00:24 PM UTC-7, J.D. wrote:
 I actually figured this out.
 
 It had nothing to do with my SQLAlchemy create_engine configuration.
 
 The data I was trying to create an object with was in ISO-8859-1 format, so I 
 just had to construct my Object the text decoded properly.
 
 Once I did this, the data was inserted into my sqlite3 table just fine.
 
 
 On Tuesday, March 3, 2015 at 1:58:32 PM UTC-7, J.D. wrote:
 Hi,
 
 I am getting the following error, when I try to execute code to insert a new 
 row into one of my tables, and I've googled for answers and tried everything 
 I could find online and nothing seems to resolve the issue.
 
 sqlalchemy.exc.ProgrammingError: (ProgrammingError) You must not use 8-bit 
 bytestrings unless you use a text_factory that can interpret 8-bit 
 bytestrings (like text_factory = str)


the error means that your unicode string has to be passed to pysqlite as a
Python unicode object, that is, in Python 2 it has to be with a “u”, u’my
string’.

if you’re losing encoding information, that means that the encoding you’re
using to decode into unicode is probably not correct.

Feel free to share the string literal and I can round trip it into SQLite
for you.



 I am using the following software:
 
 SQLAlchemy v0.9.8
 
 SQLite 3.8.8.2.
 
 I am creating my engine as follows,
 
 engine = create_engine('sqlite+pysqlite:///prototype.db', module=sqlite)
 
 #engine.raw_connection().connection.text_factory = str
 
 #engine.connect().connection.connection.text_factory = str
 
 session = sessionmaker(bind=engine)()
 
 meta.Base.metadata.bind = engine
 
 
 meta.Base.metadata.create_all(engine)
 
 The object I am trying to insert via session.add(..) has a structure similar 
 to the following: (shortened for brevity)
 
 ..
 
 id = Column(Integer, primary_key=True, unique=True, nullable=False)
 
 title = Column(String, nullable=False) // This is the column that 
 gets the Portuguese data with unicode characters -- I've tried using the 
 column type Unicode
 
 # title = Column(Unicode, nullable=False)
 
 book_id = Column(Integer, nullable=False)
 
 
 code = Column(Integer, nullable=False)
 
 ...
 
 I've tried setting the text_factory on the connection to no avail.  I'm at a 
 loss how to fix this so I can insert my data with unicode chars.
 
 Here is the SQL that is generated for the insert
 
 
 It is highly recommended that you instead just switch your application to 
 Unicode strings. u'INSERT INTO books (title, book_id, code) VALUES (?, ?, ?)' 
 ('Demana/Blitzer: Pr\x8e-c\x87lculo, 2e', '93810', 'removed')
 
 I would appreciate some insight to how to fix this issue so I can insert my 
 data.
 
 Thanks,
 
 J.D.
 
 
 
 
 
 
 
 
 -- 
 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.

-- 
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] Re: Flushed PickleType data disappearing

2015-03-03 Thread Michael Bayer


SQLRook dev...@gmail.com wrote:

 To move one step from your sample toward my codebase, I made a class method 
 to modify the pickled list.  Already, I see behavior that I cannot explain.  
 If the session is passed to modifyTarget(), you can observe the 
 targetInstance become dirty, marked as modified, and then by the end of the 
 function, the column is no longer modified, even though the contents have 
 changed twice.  How does a column become un-modified? (for scalar values, I 
 understand that an int column would in net not be modified if its value 
 changed from 6 to 10 to 6).  You can optionally not pass the session to 
 modifyTarget(), and the object won't be modified after the call.
 
 class Target(Base):
 __tablename__ = 'targets'
 id = Column(Integer, primary_key=True)
 name = Column(Unicode)
 targetList = Column(PickleType, default=[])
 
 def modifyTarget(self,dbSession=None):
 print 'target list on entry: ' + str(self.targetList)
 if dbSession:
 assert not any(dbSession.dirty)
 print 'modified on entry? ' + str(dbSession.is_modified(self))
 temp = self.targetList
 self.targetList = None
 if dbSession:
 assert any(dbSession.dirty)
 assert dbSession.is_modified(self)
 temp.append(6)
 if dbSession:
 assert any(dbSession.dirty)
 print 'session dirty objs: ' + str(dbSession.dirty)
 self.targetList, temp = temp, self.targetList#swap
 print 'target list on exit: ' + str(self.targetList) 
 if dbSession:
 assert dbSession.is_modified(self)

There’s ultimately no assignment to a new value taking place here, you’re
appending in the same collection that was already loaded. The attribute system
is smart enough to skip the expensive operation of persisting an object that
it can see is already the one that was loaded (without using the in-place 
mutation
extension, of course). Also, because you are mutating
the original loaded collection, even if you assign to this attribute a brand
new list, if it has the same values as the “temp” that is the same list it
already has present, it will compare as equal and will not be persisted.

break down like this:

def modifyTarget(self):
import pdb
pdb.set_trace()

temp = self.targetList
self.targetList = None
temp.append(6)
self.targetList = list(temp)

then run, and into pdb:

 /Users/classic/dev/sqlalchemy/test.py(18)modifyTarget()
- temp = self.targetList

# the in python identifier of the list:
(Pdb) id(self.targetList)
4357645232

# set to None
(Pdb) next
 /Users/classic/dev/sqlalchemy/test.py(19)modifyTarget()
- self.targetList = None

# arrive at the .append(), but we didn’t run it yet
(Pdb) next
 /Users/classic/dev/sqlalchemy/test.py(20)modifyTarget()
- temp.append(6)

# look at the tracked history of the attribute
(Pdb) from sqlalchemy import inspect
(Pdb) inspect(self).attrs.targetList.history
History(added=[None], unchanged=(), deleted=[[1, 2, 3]])

# we can see that the [1, 2, 3], we see in there is the same 
# list as above; SQLAlchemy certainly isn’t going to make a 
# copy of this, it wouldn’t know how in a generic sense 
# because this object could be anything, not just a list

(Pdb) id(inspect(self).attrs.targetList.history.deleted[0])
4357645232

# so if we append to the list...
(Pdb) temp.append(6)

# we are appending to the historical value that we’d be comparing to!
(Pdb) inspect(self).attrs.targetList.history
History(added=[None], unchanged=(), deleted=[[1, 2, 3, 6]])

# no matter what effort we make to reassign a brand new list to 
self.targetList….
(Pdb) self.targetList = list(temp)

# it will still *match* what’s being “replaced”, so no net change:
(Pdb) inspect(self).attrs.targetList.history
History(added=(), unchanged=[[1, 2, 3, 6]], deleted=())


basically, if you aren’t using the mutation system (which is fine, it’s
complicated), you should never be changing the value that was loaded, as
long as it isn’t expired.   Leave it alone, and when you assign, ensure that
the new value is only set up on a new object:

def modifyTarget(self):
self.targetList = self.targetList + [6]

Note it can also be made to work if you “expire” that value, so it isn’t
present in committed:

dbSession.expire(self, [“targetList”])

that would remove the “deleted” portion of history, and the attribute system
in this particular case will just assume it needs to update the value (which
is judged as cheaper in most cases than loading the old value first to test,
though this can be configured).


 def run(dbSession):
 targetInstance = Target(name='t1', targetList=[1, 2, 3])
 dbSession.add(targetInstance)
 dbSession.flush()
 
 targetInstance.modifyTarget()#pass dbSession if you like
 assert dbSession.is_modified(targetInstance)
 assert any (dbSession.dirty)
 print 'begin flush 2...'