modeling-cvs Mailing List for Object-Relational Bridge for python
Status: Abandoned
Brought to you by:
sbigaret
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(54) |
Apr
(29) |
May
(94) |
Jun
(47) |
Jul
(156) |
Aug
(132) |
Sep
(40) |
Oct
(6) |
Nov
(18) |
Dec
(24) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(18) |
Feb
(59) |
Mar
(7) |
Apr
|
May
(8) |
Jun
(2) |
Jul
(12) |
Aug
(15) |
Sep
(12) |
Oct
(6) |
Nov
(25) |
Dec
(1) |
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
(27) |
Mar
|
Apr
(16) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sbi...@us...> - 2009-07-20 07:34:16
|
Revision: 1004 http://modeling.svn.sourceforge.net/modeling/?rev=1004&view=rev Author: sbigaret Date: 2009-07-20 07:34:12 +0000 (Mon, 20 Jul 2009) Log Message: ----------- Fixed a bug reported by Bernard at knowledgeworks.plus.com on the mailing list: the generation script reported errors on correct models and refused to generate the code unless -f was supplied Modified Paths: -------------- trunk/ProjectModeling/Modeling/scripts/mdl_generate_python_code.py Modified: trunk/ProjectModeling/Modeling/scripts/mdl_generate_python_code.py =================================================================== --- trunk/ProjectModeling/Modeling/scripts/mdl_generate_python_code.py 2006-04-23 15:10:24 UTC (rev 1003) +++ trunk/ProjectModeling/Modeling/scripts/mdl_generate_python_code.py 2009-07-20 07:34:12 UTC (rev 1004) @@ -178,7 +178,7 @@ from Modeling.ModelValidation import NOT_SUPPORTED,ERROR,WARNING,INFO,DEBUG errors=MV.ModelValidationException(ignore_levels=[DEBUG,INFO,WARNING]) MV.validateModel(model, errors) - if errors: + if errors.has_errors(): log("Error: model has errors") if verbose: log(str(errors)) else: log("(-v for details)") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-23 15:10:29
|
Revision: 1003 Author: sbigaret Date: 2006-04-23 08:10:24 -0700 (Sun, 23 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=1003&view=rev Log Message: ----------- Updated: doc. explicitly mention the problems of using ZECS w/ ZEO, and the solutions Modified Paths: -------------- trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex Modified: trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex 2006-04-23 13:01:38 UTC (rev 1002) +++ trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex 2006-04-23 15:10:24 UTC (rev 1003) @@ -238,23 +238,64 @@ \label{fig:enable-bind-ec-txn-to-zope-txn} \end{figure} -%% \begin{figure} -%% \ifpdf -%% \includegraphics[width=\textwidth]{./UserGuide/ZECS} -%% \else -%% \begin{htmlonly} % HTML -%% \htmladdimg{ZECS} -%% \end{htmlonly} -%% \fi -%% %begin{latexonly} -%% \ifpdf% PDF -%% \else%LATEX/dvi -%% \fi -%% %end{latexonly} -%% \caption{Binding Zope txn to SESSION's defaultEC() txn} -%% \label{fig:enable-bind-ec-txn-to-zope-txn} -%% \end{figure} +\subsection{ZEO\label{framework-integration-zope-zeo}} +Projects using ZEO should take extra care before using the +\module{ZEditingContextSessioning} (ZECS) product. + +In ZEO environments, different Zope processes are launched. The problem is +that the ZECS product is designed to work in a MT environment, but it {\bf +cannot} share EditingContexts between different processes. + +The fact is that, you cannot share EC between different processes (so +this is not specific to zeo itself). To do such a thing, it would be +necessary to store the EC in the session along with its pending +insertions/deletions, and the whole graph of objects as well since +pending modifications can exist in-memory. It is not possible in the +current implementation, and there is no plan for making this available +(for example, in the zope/zeo case, this means +that every single object and their attributes should be made +zodb-Persistent so that they can be stored in a session object). + + +In fact, Zope/zeo \& {\sc zodb} address the same problem by opening/ closing a +transaction at the beginning/end of each request loop. In this situation, if +you need to hold back changes between two or three requests/pages, you won't +change the real object in the "main" zodb, rather you'll store the changes in +a session object. + +ZECS faces the same problem. Here are the options you have, in this case: + +\begin{itemize} +\item If every changes made in a request loop is committed/rolled back at the + end of the request, then you'll made changes directly in the object. + You can do the same w/ ZECS: this is why it has an option binding + EC-transactions to zope transactions, + cf.~\ref{framework-integration-zope-options}. + +\item on the other hand, if the modifications of, say, a given objet should be + made accross different requests/pages before being permanently stored in + a db (either zodb, or rdbms), you'll just make it the usual way; e.g. + storing the changes in a session-object, then in the last page, + committing the changes into the object and the DB. + +\end{itemize} + +A third solution is possible, where you can use the ZECS even in +ZEO environment. EditingContext cannot be shared accross +processes, but if you can make sure that a given session is always +served by the same zeoclient, then you'll get back the "full power" of +having a session-EC, with pending (uncommitted) changes crossing the +page requests. + +\paragraph*{Using Pound}~\\ + +\ulink{Pound}{http://www.apsis.ch/pound/} is a load balancer that can +distribute the load among several Zope servers running on top of ZEO. Since +it has a feature that allows to redirect requests to a zeoclient on per +session basis (by IP or user), you can use it to solve the problem of using +ZECS in a ZEO environment. To enable this feature: TODO + %% \section{Others\label{framework-integration-others}} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-23 13:01:46
|
Revision: 1002 Author: sbigaret Date: 2006-04-23 06:01:38 -0700 (Sun, 23 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=1002&view=rev Log Message: ----------- Fixed bug #1442766: ZEditingContextSessioning was incorrectly reporting an error in ZEO environments Modified Paths: -------------- trunk/ZModeling/CHANGES trunk/ZModeling/ZEditingContextSessioning/__init__.py Modified: trunk/ZModeling/CHANGES =================================================================== --- trunk/ZModeling/CHANGES 2006-04-22 22:22:45 UTC (rev 1001) +++ trunk/ZModeling/CHANGES 2006-04-23 13:01:38 UTC (rev 1002) @@ -1,8 +1,16 @@ CHANGES for ZModeling ===================== -Current release is: 0.9-pre-15 +Current release is: 0.9 + * ZEditingContextSessioning: Fixed bug #1442766: the product was incorrectly + reporting an error in ZEO environments. + +0.9 (2006/02/26) +---------------- + + * Now distributed under a 3-clause BSD-style license, see LICENSE for details + 0.9-pre-15 (2003/09/13) ----------------------- Modified: trunk/ZModeling/ZEditingContextSessioning/__init__.py =================================================================== --- trunk/ZModeling/ZEditingContextSessioning/__init__.py 2006-04-22 22:22:45 UTC (rev 1001) +++ trunk/ZModeling/ZEditingContextSessioning/__init__.py 2006-04-23 13:01:38 UTC (rev 1002) @@ -72,6 +72,8 @@ except: pass +sessionDeletion_hook_path = '/Control_Panel/Products/ZEditingContextSessioning/sessionDeletion_hook' + def defaultEditingContext(session): """ Returns the EditingContext bound to 'session' @@ -89,31 +91,47 @@ app=context._ProductContext__app sessionDataContainer=app.temp_folder.session_data - if sessionDataContainer.getDelNotificationTarget(): - zLOG.LOG('Products.ZEditingContextSessioning', zLOG.ERROR, - "The session data container's destruction callback already set -- installation aborted") - return + installed_deletion_hook = sessionDataContainer.getDelNotificationTarget() + if installed_deletion_hook: + if installed_deletion_hook in (sessionDeletion_hook_path, + sessionDeletion_hook): + + zLOG.LOG('Products.ZEditingContextSessioning', zLOG.INFO, + "session's deletion hook already registered") + + else: + zLOG.LOG('Products.ZEditingContextSessioning', zLOG.ERROR, + "The session data container's destruction callback already set -- installation aborted") + return + else: + ## Supply the path to the method rather than the method itself, or the + ## Transient Object Container's ZMI will not show a meaningful value for + ## its field 'Script to call when objects are deleted' + #sessionDataContainer.setDelNotificationTarget(sessionDeletion_hook) + zLOG.LOG('Products.ZEditingContextSessioning', zLOG.INFO, + "Registering the session's deletion hook") + sessionDataContainer.setDelNotificationTarget(sessionDeletion_hook_path) + # There is no SessionObject, just Transient Object if getattr(TransientObject, 'defaultEditingContext', None): - zLOG.LOG('Products.ZEditingContextSessioning', zLOG.ERROR, - "TransientObject already has a 'defaultEditingContext' attribute -- installation aborted") + zLOG.LOG('Products.ZEditingContextSessioning', zLOG.INFO, + "TransientObject already has a 'defaultEditingContext' attribute") + else: + zLOG.LOG('Products.ZEditingContextSessioning', zLOG.INFO, + "Adding method 'defaultEditingContext()' to TransientObject") + TransientObject.defaultEditingContext=defaultEditingContext - return - TransientObject.defaultEditingContext=defaultEditingContext - - ## Supply the path to the method rather than the method itself, or the - ## Transient Object Container's ZMI will not show a meaningful value for - ## its field 'Script to call when objects are deleted' - #sessionDataContainer.setDelNotificationTarget(sessionDeletion_hook) - sessionDataContainer.setDelNotificationTarget('/Control_Panel/Products/ZEditingContextSessioning/sessionDeletion_hook') - product=app.Control_Panel.Products.ZEditingContextSessioning bind_to_zope_txn='bind_saveChanges_to_zope_transactions' if bind_to_zope_txn not in [p['id'] for p in product._properties]: product.manage_addProperty(id=bind_to_zope_txn, type='boolean', value=0) - + else: + zLOG.LOG('Products.ZEditingContextSessioning', zLOG.INFO, + "Product's Control Panel: Properties tab already initialized") + + # ?? Why did I need this? #context._ProductContext__prod.sessionDeletion_hook=sessionDeletion_hook This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-22 22:22:51
|
Revision: 1001 Author: sbigaret Date: 2006-04-22 15:22:45 -0700 (Sat, 22 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=1001&view=rev Log Message: ----------- Feature Request #978800 extended for MySQL: PKs are also fetched in a single request (instead of n requests in one transaction) Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLAdaptorChannel.py Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-04-22 19:07:12 UTC (rev 1000) +++ trunk/ProjectModeling/CHANGES 2006-04-22 22:22:45 UTC (rev 1001) @@ -7,8 +7,12 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Feature Request #978800 extended for MySQL: PKs are also fetched in a + single request (instead of n requests in one transaction) + * Feature Request #978800: "SQLite adaptor: get X primary keys at once" - PKs are now retrieved in a single request. + PKs are now retrieved in a single request (instead of n requests in one + transaction) * Fixed bug #1474720: when saving changes, the PKs needed for the inserted objects are retrieved one after the other, opening and closing a Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLAdaptorChannel.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLAdaptorChannel.py 2006-04-22 19:07:12 UTC (rev 1000) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLAdaptorChannel.py 2006-04-22 22:22:45 UTC (rev 1001) @@ -68,23 +68,23 @@ try: pkName=anEntity.primaryKeyAttributeNames()[0] pkRootName=anEntity.primaryKeyRootName() - statements=["UPDATE PK_SEQ_%s SET id=LAST_INSERT_ID(id+1)"%pkRootName, + statements=["UPDATE PK_SEQ_%s SET id=LAST_INSERT_ID(id+%i)"%(pkRootName,count), "select LAST_INSERT_ID()"] result=[] - for idx in range(count): - for statement in statements: - db_info('Evaluating: %s'%statement) - try: - self.dbAPI_cursor().execute(statement) - except: - exctype, value = sys.exc_info()[:2] - msg="Couldn't evaluate expression %s. Reason: %s:%s"%(statement, exctype, value) - db_error(msg) - raise GeneralAdaptorException, msg - - MySQLAdaptorChannel._count_for_execute+=1 + for statement in statements: + db_info('Evaluating: %s'%statement) + try: + self.dbAPI_cursor().execute(statement) + except: + exctype, value = sys.exc_info()[:2] + msg="Couldn't evaluate expression %s. Reason: %s:%s"%(statement, exctype, value) + db_error(msg) + raise GeneralAdaptorException, msg + + MySQLAdaptorChannel._count_for_execute+=1 - result.append({pkName :self.dbAPI_cursor().fetchone()[0]}) + result = self.dbAPI_cursor().fetchone()[0] + result = [{pkName : v+1} for v in range(result-count,result)] return tuple(result) finally: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-22 19:07:23
|
Revision: 1000 Author: sbigaret Date: 2006-04-22 12:07:12 -0700 (Sat, 22 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=1000&view=rev Log Message: ----------- Feature Request #978800: "SQLite adaptor: get X primary keys at once". PKs are now retrieved in a single request Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorChannel.py Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-04-22 18:47:08 UTC (rev 999) +++ trunk/ProjectModeling/CHANGES 2006-04-22 19:07:12 UTC (rev 1000) @@ -7,6 +7,9 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Feature Request #978800: "SQLite adaptor: get X primary keys at once" + PKs are now retrieved in a single request. + * Fixed bug #1474720: when saving changes, the PKs needed for the inserted objects are retrieved one after the other, opening and closing a transaction for every PK. PKs are now fetched by batch, in a single Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorChannel.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorChannel.py 2006-04-22 18:47:08 UTC (rev 999) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorChannel.py 2006-04-22 19:07:12 UTC (rev 1000) @@ -69,23 +69,22 @@ try: pkName=anEntity.primaryKeyAttributeNames()[0] pkRootName=anEntity.primaryKeyRootName() - statements=["UPDATE PK_SEQ_%s SET id=((select max(id) from PK_SEQ_%s)+1)"%(pkRootName,pkRootName), + statements=["UPDATE PK_SEQ_%s SET id=((select max(id) from PK_SEQ_%s)+%i)"%(pkRootName,pkRootName,count), "select id FROM PK_SEQ_%s"%pkRootName] - result=[] - for idx in range(count): - for statement in statements: - db_info('Evaluating: %s'%statement) - try: - self.dbAPI_cursor().execute(statement) - except: - exctype, value = sys.exc_info()[:2] - msg="Couldn't evaluate expression %s. Reason: %s:%s"%(statement, exctype, value) - db_error(msg) - raise GeneralAdaptorException, msg - - SQLiteAdaptorChannel._count_for_execute+=1 + for statement in statements: + db_info('Evaluating: %s'%statement) + try: + self.dbAPI_cursor().execute(statement) + except: + exctype, value = sys.exc_info()[:2] + msg="Couldn't evaluate expression %s. Reason: %s:%s"%(statement, exctype, value) + db_error(msg) + raise GeneralAdaptorException, msg + + SQLiteAdaptorChannel._count_for_execute+=1 - result.append({pkName :self.dbAPI_cursor().fetchone()[0]}) + result = self.dbAPI_cursor().fetchone()[0] + result = [{pkName : v+1} for v in range(result-count,result)] return tuple(result) finally: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-22 18:47:15
|
Revision: 999 Author: sbigaret Date: 2006-04-22 11:47:08 -0700 (Sat, 22 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=999&view=rev Log Message: ----------- Fixed bug #1474720: when saving changes, the PKs needed for the inserted objects were retrieved one after the other, opening and closing a transaction for every PK Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/DatabaseContext.py Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-04-22 18:36:10 UTC (rev 998) +++ trunk/ProjectModeling/CHANGES 2006-04-22 18:47:08 UTC (rev 999) @@ -7,6 +7,12 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Fixed bug #1474720: when saving changes, the PKs needed for the inserted + objects are retrieved one after the other, opening and closing a + transaction for every PK. PKs are now fetched by batch, in a single + transaction for all objects having the same entity. + This should make inserting a lot of objects really faster. + * Feature request #1011515: Configurability of ABORT/COMMIT on read-only transactions (for postgresql). Modified: trunk/ProjectModeling/Modeling/DatabaseContext.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseContext.py 2006-04-22 18:36:10 UTC (rev 998) +++ trunk/ProjectModeling/Modeling/DatabaseContext.py 2006-04-22 18:47:08 UTC (rev 999) @@ -1066,18 +1066,23 @@ # get the primary keys for inserted objects - # this could be made more efficient if PKs were asked within a single - # round-trip to the DB + # 1st: sort the inserted objects by entity + # 2nd: fetch the primary keys, one entity after the other + # The purpose is to make one and only one round-trip to the db + # (==one transaction) per entity self.lock() try: channel=self.availableChannel().adaptorChannel() + entity_to_gids={} for gID in self._inserted_gIDs: - entity=ec.objectForGlobalID(gID).classDescription().entity() - pk=channel.primaryKeysForNewRowsWithEntity(1, entity) - self._pks_for_inserted_gIDs[gID]=pk[0] - - newGid=KeyGlobalID(entity.name(), self._pks_for_inserted_gIDs[gID]) - self.__temporaryGID_to_KeyGlobalID[gID]=newGid + entity_to_gids.setdefault(ec.objectForGlobalID(gID).classDescription().entity(), []).append(gID) + + for entity, gIDs in entity_to_gids.items(): + pks=channel.primaryKeysForNewRowsWithEntity(len(gIDs), entity) + for gID, pk in map(None, gIDs, pks): + self._pks_for_inserted_gIDs[gID]=pk + newGid=KeyGlobalID(entity.name(), self._pks_for_inserted_gIDs[gID]) + self.__temporaryGID_to_KeyGlobalID[gID]=newGid finally: self.unlock() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-22 18:36:17
|
Revision: 998 Author: sbigaret Date: 2006-04-22 11:36:10 -0700 (Sat, 22 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=998&view=rev Log Message: ----------- Feature request #1011515: Configurability of ABORT/COMMIT on read-only transactions (postgresql/psycopg) Modified Paths: -------------- trunk/ProjectModeling/CHANGES Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-04-22 14:00:35 UTC (rev 997) +++ trunk/ProjectModeling/CHANGES 2006-04-22 18:36:10 UTC (rev 998) @@ -7,6 +7,9 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Feature request #1011515: Configurability of ABORT/COMMIT on read-only + transactions (for postgresql). + * Fixed bug #855257 and #918092: objects w/ string values containing simple quotes, and fetch requests containing simple quotes, were not properly handled by the SQLite and Oracle adaptor layers (they were escaped with This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-22 14:00:48
|
Revision: 997 Author: sbigaret Date: 2006-04-22 07:00:35 -0700 (Sat, 22 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=997&view=rev Log Message: ----------- Feature request #1011515: Configurability of ABORT/COMMIT on read-only transactions (postgresql/psycopg) Modified Paths: -------------- trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlAdaptorContext.py trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/__init__.py trunk/ProjectModeling/Modeling/TODO trunk/ProjectModeling/Modeling/doc/UserGuide/EnvironmentVariables.tex trunk/ProjectModeling/Modeling/utils.py Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlAdaptorContext.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlAdaptorContext.py 2006-04-22 13:34:27 UTC (rev 996) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlAdaptorContext.py 2006-04-22 14:00:35 UTC (rev 997) @@ -33,6 +33,39 @@ """ Concrete AdaptorContext for Postgresql [module psycopg,pgdb or pypgsql] """ + + def shouldCommitReadonlyTransactions(self): + """ + By default, the Postgresql Adaptor Layer rollbacks transactions after a + fetch, when using psycopg. The reason is that, if the isolation level is + set to serializable (it was the default in psycopg in former releases, and + is now read from database settings), changes made in other processes won't + be seen until the transaction is finished (see `Transaction Isolation + <http://www.postgresql.org/docs/8.1/static/transaction-iso.html>`_ in + Postgresql's documentation). + + The default behaviour can be changed in two different ways: + + - setting the environment variable ``MDL_COMMIT_AFTER_FETCH`` to any value + (except the empty string) + + - programmatically:: + + from Modeling.DatabaseAdaptors import PostgresqlAdaptorLayer + PostgresqlAdaptorLayer.commit_readonly_transactions = 1 + + The value is interpreted as any python boolean value. + + The environment variable is ignored as soon as it is set programmatically. + """ + from Modeling.utils import unset + from Modeling.DatabaseAdaptors.PostgresqlAdaptorLayer \ + import commit_readonly_transactions + if commit_readonly_transactions is not unset: + return commit_readonly_transactions + import os + return os.environ.get('MDL_COMMIT_AFTER_FETCH', None) + def adaptorChannelDidClose(self, aChannel): """ Invokes AbstractDBAPI2AdaptorContext.adaptorChannelDidClose(), then @@ -48,9 +81,14 @@ AbstractDBAPI2AdaptorContext.adaptorChannelDidClose(self, aChannel) from PostgresqlAdaptor import _uses_psycopg if _uses_psycopg and not self.hasOpenChannels() and self._cnx: - ## rollbacks the connexion - db_debug('psycopg specifics: ROLLBACK on cnx') - self._cnx.rollback() + if self.shouldCommitReadonlyTransactions(): + ## rollbacks the connexion + db_debug('psycopg specifics: COMMIT on cnx') + self._cnx.commit() + else: + ## rollbacks the connexion + db_debug('psycopg specifics: ROLLBACK on cnx') + self._cnx.rollback() def createAdaptorChannel(self): """ Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/__init__.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/__init__.py 2006-04-22 13:34:27 UTC (rev 996) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/__init__.py 2006-04-22 14:00:35 UTC (rev 997) @@ -56,3 +56,6 @@ def adaptorFactory(): from PostgresqlAdaptor import PostgresqlAdaptor return PostgresqlAdaptor + +from Modeling.utils import unset +commit_readonly_transactions = unset Modified: trunk/ProjectModeling/Modeling/TODO =================================================================== --- trunk/ProjectModeling/Modeling/TODO 2006-04-22 13:34:27 UTC (rev 996) +++ trunk/ProjectModeling/Modeling/TODO 2006-04-22 14:00:35 UTC (rev 997) @@ -182,6 +182,10 @@ Database Layer (in Access Layer) + * in relation to feature request #1011515 and isolation level: we should + check the othe postgresql's python adaptors, and also what the situation + is w/ other databases (wrt possible isolation level issues). + * Snapshotting of to-many relationships is implemented but unused for the moment being. Modified: trunk/ProjectModeling/Modeling/doc/UserGuide/EnvironmentVariables.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/UserGuide/EnvironmentVariables.tex 2006-04-22 13:34:27 UTC (rev 996) +++ trunk/ProjectModeling/Modeling/doc/UserGuide/EnvironmentVariables.tex 2006-04-22 14:00:35 UTC (rev 997) @@ -138,6 +138,34 @@ anymore) ; this does not affect the runtime core for the moment being. } {\code{'7.2'} (default), \code{'7.3'}} \hline +\lineiii{MDL_COMMIT_AFTER_FETCH}{}{} +\lineiii{}{By default, the Posgresql Adaptor Layer rollbacks transactions after + a fetch, when using psycopg. The reason is that, if the isolation level is + set to serializable (it was the default in psycopg in former releases, and + is now read from database settings), changes made in other processes won't + be seen until the transaction is finished (see Transaction + Isolation in Postgresql's documentation, at + http://www.postgresql.org/docs/8.1/static/transaction-iso.html). + \newline~\newline + Setting this variable to any value (apart from the empty string) changes the + default behaviour, so that every transaction opened for fetching is + committed instead of being rolled back. This feature was requested because + ``this can be a problem while debugging the log of an application, where + the ABORT will be the majority of the transactions'' (see the corresponding + feature request at + https://sourceforge.net/tracker/index.php?func=detail\&aid=1011515\&group_id=58935\&atid=489338). + \newline~\newline + It can also be set programmatically:\newline +{\small +\inlineverb{from Modeling.DatabaseAdaptors import PostgresqlAdaptorLayer} +\inlineverb{PostgresqlAdaptorLayer.commit_readonly_transactions = 1} +} +The value is interpreted as any python boolean value. +\newline~\newline +The environment variable is ignored as soon as it is set programmatically. + } + {e.g. '1', 'YES' (plus the empty string for de-activation)} +\hline \end{longtableiii}\label{tab:env-vars-postgresql} \newpage Modified: trunk/ProjectModeling/Modeling/utils.py =================================================================== --- trunk/ProjectModeling/Modeling/utils.py 2006-04-22 13:34:27 UTC (rev 996) +++ trunk/ProjectModeling/Modeling/utils.py 2006-04-22 14:00:35 UTC (rev 997) @@ -267,3 +267,10 @@ if os.environ.has_key('MDL_PERMANENT_DB_CONNECTION'): msg="Environment variable MDL_PERMANENT_DB_CONNECTION is deprecated since 0.9pre17 and it has no effect anymore. The framework's default behaviour is now to leave the database connection opened. This variable has been replaced by the variable MDL_TRANSIENT_DB_CONNECTION which has the inverse semantics. Please refer to the User's Guide, appendix Environment Variables, for further details" warnings.warn(msg, DeprecationWarning) + +unset = [] + +def is_unset(value): + global unset + return value is unset + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-22 13:34:36
|
Revision: 996 Author: sbigaret Date: 2006-04-22 06:34:27 -0700 (Sat, 22 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=996&view=rev Log Message: ----------- Removed useless commented code Modified Paths: -------------- trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorContext.py Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorContext.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorContext.py 2006-04-19 20:30:59 UTC (rev 995) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/SQLiteAdaptorContext.py 2006-04-22 13:34:27 UTC (rev 996) @@ -33,24 +33,6 @@ """ Concrete AdaptorContext for SQLite [module pysqlite] """ - #def adaptorChannelDidClose(self, aChannel): - # """ - # Invokes AbstractDBAPI2AdaptorContext.adaptorChannelDidClose(), then - # rollbacks the connection if it still exists (it might have been closed by - # the superclass' method depending on the configuration) AND if the adaptor - # uses psycopg AND if there is no more opened channels. - # - # The reason for that is that psycopg insolates each connection from - # another, hence if an other process make changes to the database these - # changes wont be seen unless the connection itself is closed or rolled - # back. - # """ - # AbstractDBAPI2AdaptorContext.adaptorChannelDidClose(self, aChannel) - # from SQLiteAdaptor import _uses_psycopg - # if _uses_psycopg and not self.hasOpenChannels() and self._cnx: - # ## rollbacks the connexion - # db_debug('psycopg specifics: ROLLBACK on cnx') - # self._cnx.rollback() def createAdaptorChannel(self): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-19 20:31:10
|
Revision: 995 Author: sbigaret Date: 2006-04-19 13:30:59 -0700 (Wed, 19 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=995&view=rev Log Message: ----------- Fixed bug #855257 and #918092: objects w/ string values containing simple quotes, and fetch requests containing simple quotes, were not properly handled by the SQLite and Oracle adaptor layers Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py trunk/ProjectModeling/Modeling/SQLExpression.py trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-04-19 19:39:18 UTC (rev 994) +++ trunk/ProjectModeling/CHANGES 2006-04-19 20:30:59 UTC (rev 995) @@ -7,8 +7,14 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Fixed bug #855257 and #918092: objects w/ string values containing simple + quotes, and fetch requests containing simple quotes, were not properly + handled by the SQLite and Oracle adaptor layers (they were escaped with + backslashes, they are now replaced by two consecutive single quotes, + following the SQL standard) + * Fixed bug #1471992: objects w/ values containing a single backslash are - not properly handled by the MySQL and Postgresql adaptor layer (the + not properly handled by the MySQL and Postgresql adaptor layers (the generated SQLExpression are incorrect; for example, insertions of such objects failed) Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py 2006-04-19 19:39:18 UTC (rev 994) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py 2006-04-19 20:30:59 UTC (rev 995) @@ -238,8 +238,9 @@ def sqlStringForString(self, aString): """ Formats 'aString' and returns the string suitable for inclusion in a SQL - statement. SQLExpression's implementation surrounds the string with - simple quotes, and back-quotes any simple quotes 'aString' may have. + statement. This method surrounds the string with simple quotes, so, every + simple quote in 'aString' is transformed into a sequence a two simple + quotes. Single backslashes are escaped as well. It returns 'NULL' if 'aString' is None. See also: formatValueForAttribute() @@ -248,7 +249,7 @@ # quote the string: interprets the strings aString = repr(aString)[1:-1] from Modeling.SQLExpression import escapeQuote - str=escapeQuote.sub("\\'", aString) + str=escapeQuote.sub("''", aString) return "'"+str+"'" else: return 'NULL' Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py 2006-04-19 19:39:18 UTC (rev 994) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py 2006-04-19 20:30:59 UTC (rev 995) @@ -116,8 +116,9 @@ def sqlStringForString(self, aString): """ Formats 'aString' and returns the string suitable for inclusion in a SQL - statement. SQLExpression's implementation surrounds the string with - simple quotes, and back-quotes any simple quotes 'aString' may have. + statement. This method surrounds the string with simple quotes, so, every + simple quote in 'aString' is transformed into a sequence a two simple + quotes. Single backslashes are escaped as well. It returns 'NULL' if 'aString' is None. See also: formatValueForAttribute() @@ -126,7 +127,7 @@ # quote the string: postgresql interprets the strings aString = repr(aString)[1:-1] from Modeling.SQLExpression import escapeQuote - str=escapeQuote.sub("\\'", aString) + str=escapeQuote.sub("''", aString) return "'"+str+"'" else: return 'NULL' Modified: trunk/ProjectModeling/Modeling/SQLExpression.py =================================================================== --- trunk/ProjectModeling/Modeling/SQLExpression.py 2006-04-19 19:39:18 UTC (rev 994) +++ trunk/ProjectModeling/Modeling/SQLExpression.py 2006-04-19 20:30:59 UTC (rev 995) @@ -1387,14 +1387,15 @@ def sqlStringForString(self, aString): """ Formats 'aString' and returns the string suitable for inclusion in a SQL - statement. SQLExpression's implementation surrounds the string with - simple quotes, and back-quotes any simple quotes 'aString' may have. + statement. This method surrounds the string with simple quotes, so, every + simple quote in 'aString' is transformed into a sequence a two simple + quotes. It returns 'NULL' if 'aString' is None. See also: formatValueForAttribute() """ if aString is not None: - str=escapeQuote.sub("\\'", aString) + str=escapeQuote.sub("''", aString) return "'"+str+"'" else: return 'NULL' Modified: trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py =================================================================== --- trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py 2006-04-19 19:39:18 UTC (rev 994) +++ trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py 2006-04-19 20:30:59 UTC (rev 995) @@ -1425,16 +1425,19 @@ ec.insert(b1); ec.insert(b2); ec.insert(b3); ec.insert(b4) ec.saveChanges() + ec=EditingContext() res=ec.fetch('Book', 'title == "abc\\n"') self.assertEqual(len(res), 1) self.assertEqual(res[0].getTitle(), r"abc\n") self.assertEqual(res[0].getPrice(), 1) + ec=EditingContext() res=ec.fetch('Book', 'title == "abc\n"') self.assertEqual(len(res), 1) self.assertEqual(res[0].getTitle(), "abc\n") self.assertEqual(res[0].getPrice(), 2) + ec=EditingContext() res=ec.fetch('Book', 'title == "\\"') self.assertEqual(len(res), 1) self.assertEqual(res[0].getTitle(), "\\") @@ -1444,6 +1447,37 @@ #self.assertEqual(res[0].getTitle(), "abc%d") # TBD: with LIKE and ILIKE + def test_31_insert_and_fetch_single_quotes(self): + "[EditingContext] insert and fetch single quotes" + # bug #855257 and #918092 + ec=EditingContext() + b1=Book(); b1.setPrice(1.0); b1.setTitle("ab'c") + b2=Book(); b2.setPrice(2.0); b2.setTitle("'") + b3=Book(); b3.setPrice(3.0); b3.setTitle("ab''c") + ec.insert(b1); ec.insert(b2); ec.insert(b3) + ec.saveChanges() # should not fail + + ec=EditingContext() + res=ec.fetch('Book', 'title == "ab\'\'c"') + self.assertEqual(len(res), 1) + self.assertEqual(res[0].getTitle(), "ab''c") + self.assertEqual(res[0].getPrice(), 3) + + ec=EditingContext() + res=ec.fetch('Book', 'title == "ab\'c"') + self.assertEqual(len(res), 1) + self.assertEqual(res[0].getTitle(), "ab'c") + self.assertEqual(res[0].getPrice(), 1) + + res=ec.fetch('Book', 'title == "\'"') + self.assertEqual(len(res), 1) + self.assertEqual(res[0].getTitle(), "'") + self.assertEqual(res[0].getPrice(), 2) + + ec=EditingContext() + res=ec.fetch('Book', '''title == "ab''''c"''') + self.assertEqual(len(res), 0) + def test_999_customSQLQuery(self): "[EditingContext] custom SQL Query" fs=FetchSpecification(entityName='Writer') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-19 19:39:32
|
Revision: 994 Author: sbigaret Date: 2006-04-19 12:39:18 -0700 (Wed, 19 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=994&view=rev Log Message: ----------- Fix for bug #1471992: objects w/ values containing a single backslash are not properly handled by the MySQL and Postgresql adaptor layers Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-04-15 09:48:43 UTC (rev 993) +++ trunk/ProjectModeling/CHANGES 2006-04-19 19:39:18 UTC (rev 994) @@ -7,6 +7,11 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Fixed bug #1471992: objects w/ values containing a single backslash are + not properly handled by the MySQL and Postgresql adaptor layer (the + generated SQLExpression are incorrect; for example, insertions of such + objects failed) + * Fixed bug #621210: when __cmp__ (and/or, possibly, other special methods such as __eq__ or __ne__) was defined in a CustomObject, it was possible to enter a infinite loop. The fix consisted in making sure that the Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py 2006-04-15 09:48:43 UTC (rev 993) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py 2006-04-19 19:39:18 UTC (rev 994) @@ -235,7 +235,24 @@ else: return SQLExpression.sqlStringForSelector(self, selector, value) + def sqlStringForString(self, aString): + """ + Formats 'aString' and returns the string suitable for inclusion in a SQL + statement. SQLExpression's implementation surrounds the string with + simple quotes, and back-quotes any simple quotes 'aString' may have. + It returns 'NULL' if 'aString' is None. + See also: formatValueForAttribute() + """ + if aString is not None: + # quote the string: interprets the strings + aString = repr(aString)[1:-1] + from Modeling.SQLExpression import escapeQuote + str=escapeQuote.sub("\\'", aString) + return "'"+str+"'" + else: + return 'NULL' + if mysql_server_version()[:2]>=(4,0): MySQLSQLExpression.SQL92_join=1 else: Modified: trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py 2006-04-15 09:48:43 UTC (rev 993) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py 2006-04-19 19:39:18 UTC (rev 994) @@ -25,20 +25,7 @@ from Modeling.SQLExpression import SQLExpression, DateType, CharacterType import string -import re -esc_question_tmp_replct='MDL_ESCAPED_QUESTION_MARK_MDL' -esc_star_tmp_replct='MDL_ESCAPED_STAR_MDL' - -star=re.compile('\*') -escaped_star=re.compile(r'\\\*') -question_mark=re.compile('\?') -escaped_question_mark=re.compile(r'\\\?') -percent=re.compile('%') -underscore=re.compile('_') -anti_escaped_star=re.compile(esc_star_tmp_replct) -anti_esc_question_mark=re.compile(esc_question_tmp_replct) - class PostgresqlSQLExpression(SQLExpression): """ @@ -46,6 +33,25 @@ valueTypeForExternalTypeMapping() to add some new """ + def ____addInsertListAttribute(self, attribute, value): + """ + + Parameters: + + attribute -- an Attribute object + + value -- the value to store + + """ + sqlAttr=self.sqlStringForAttributeNamed(attribute.name()) + sqlValue=self.sqlStringForValue(value, attribute.name()) + #print '### sqlAttr: %s / sqlValue: %s'%(sqlAttr, sqlValue) + self.appendItemToListString(sqlAttr, self._listString) + import pdb ; pdb.set_trace() + if type(sqlValue) is type(''): + sqlValue = repr(sqlValue) + self.appendItemToListString(sqlValue, self._valueList) + def columnTypeStringForAttribute(self, attribute): """ Overrides default implementation to handle TEXT field properly. @@ -107,21 +113,24 @@ """ return '\\\\' - def sqlPatternFromShellPatternWithEscapeCharacter(self, pattern, escapeChar): + def sqlStringForString(self, aString): """ - Overrides default behaviour so that '%' is changed to '\\%' instead of - '\%': postgresql interprets backslashes in strings + Formats 'aString' and returns the string suitable for inclusion in a SQL + statement. SQLExpression's implementation surrounds the string with + simple quotes, and back-quotes any simple quotes 'aString' may have. + It returns 'NULL' if 'aString' is None. + + See also: formatValueForAttribute() """ - pattern=percent.sub(r'\\\\%', pattern) - pattern=underscore.sub(r'\\\\_', pattern) - pattern=escaped_question_mark.sub(esc_question_tmp_replct, pattern) - pattern=question_mark.sub('_', pattern) - pattern=escaped_star.sub(esc_star_tmp_replct, pattern) - pattern=star.sub('%', pattern) - pattern=anti_escaped_star.sub('*', pattern) - pattern=anti_esc_question_mark.sub('?', pattern) - return pattern - + if aString is not None: + # quote the string: postgresql interprets the strings + aString = repr(aString)[1:-1] + from Modeling.SQLExpression import escapeQuote + str=escapeQuote.sub("\\'", aString) + return "'"+str+"'" + else: + return 'NULL' + def valueTypeForExternalTypeMapping(self): """ Modified: trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py =================================================================== --- trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py 2006-04-15 09:48:43 UTC (rev 993) +++ trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py 2006-04-19 19:39:18 UTC (rev 994) @@ -1414,22 +1414,31 @@ self.failUnless(rabelais.isFault()) rabelais.getLastName() - def _test_29_fetch_backslash(self): + def test_30_fetch_backslash(self): "[EditingContext] fetch real backslash" # bug # ec=EditingContext() - b1=Book(); b1.setTitle(r'abc\n') - b2=Book(); b2.setTitle('abc\\\\') - b3=Book(); b3.setTitle('\\') - ec.insert(b1); ec.insert(b2); ec.insert(b3) + b1=Book(); b1.setPrice(1.0); b1.setTitle(r'abc\n') + b2=Book(); b2.setPrice(2.0); b2.setTitle('abc\n') + b3=Book(); b3.setPrice(3.0); b3.setTitle('\\') + b4=Book(); b4.setPrice(4.0); b4.setTitle(r'\\') + ec.insert(b1); ec.insert(b2); ec.insert(b3); ec.insert(b4) ec.saveChanges() res=ec.fetch('Book', 'title == "abc\\n"') self.assertEqual(len(res), 1) self.assertEqual(res[0].getTitle(), r"abc\n") + self.assertEqual(res[0].getPrice(), 1) + + res=ec.fetch('Book', 'title == "abc\n"') + self.assertEqual(len(res), 1) + self.assertEqual(res[0].getTitle(), "abc\n") + self.assertEqual(res[0].getPrice(), 2) + res=ec.fetch('Book', 'title == "\\"') self.assertEqual(len(res), 1) self.assertEqual(res[0].getTitle(), "\\") + self.assertEqual(res[0].getPrice(), 3) #res=ec.fetch('Book', 'title like "*abc%d*"') #self.assertEqual(len(res), 1) #self.assertEqual(res[0].getTitle(), "abc%d") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-15 09:48:49
|
Revision: 993 Author: sbigaret Date: 2006-04-15 02:48:43 -0700 (Sat, 15 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=993&view=rev Log Message: ----------- misc. doc corrections Modified Paths: -------------- trunk/ProjectModeling/Modeling/doc/HomePage/main.tex trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex Modified: trunk/ProjectModeling/Modeling/doc/HomePage/main.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/HomePage/main.tex 2006-04-15 09:44:54 UTC (rev 992) +++ trunk/ProjectModeling/Modeling/doc/HomePage/main.tex 2006-04-15 09:48:43 UTC (rev 993) @@ -34,11 +34,11 @@ %\tableofcontents -Please have a look at some elements of \begin{rawhtml}<a +You can have a look at some elements of \begin{rawhtml}<a href="UserGuide/intro.html">history</a>\end{rawhtml}, which explains why, and how, I did this, and where my ''inspiration'' came from: the Enterprise Object Framework (TM) from Apple, now integrated to their WebObjects application -server. That E.O.F.(TM) framework is a killer app. in itself! +server. See also: \begin{rawhtml}<a href="features.html">the list of the main Modified: trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex 2006-04-15 09:44:54 UTC (rev 992) +++ trunk/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex 2006-04-15 09:48:43 UTC (rev 993) @@ -232,7 +232,7 @@ %% $COPY_GRAPHICS = 1 unless defined($COPY_GRAPHICS); \begin{figure} \ifpdf \includegraphics[width=\textwidth]{./UserGuide/ZECS} -\else \htmladdimg{ZECS} %\includegraphics[width=10cm]{./UserGuide/ZECS} +\else \htmladdimg{ZECS.png} %\includegraphics[width=10cm]{./UserGuide/ZECS} \fi \caption{Binding Zope txn to SESSION's defaultEC() txn} \label{fig:enable-bind-ec-txn-to-zope-txn} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-15 09:45:08
|
Revision: 992 Author: sbigaret Date: 2006-04-15 02:44:54 -0700 (Sat, 15 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=992&view=rev Log Message: ----------- was not under subversion control Added Paths: ----------- trunk/ProjectModeling/Modeling/doc/bug861048.txt Added: trunk/ProjectModeling/Modeling/doc/bug861048.txt =================================================================== --- trunk/ProjectModeling/Modeling/doc/bug861048.txt (rev 0) +++ trunk/ProjectModeling/Modeling/doc/bug861048.txt 2006-04-15 09:44:54 UTC (rev 992) @@ -0,0 +1,77 @@ +Bug #861048: Invalid FK constraints in generated DB schema +========================================================== + +:Author: `S\xE9bastien Bigaret`_ + +.. _`S\xE9bastien Bigaret`: mailto:Seb...@en... + + +The bug described here cannot only be fixed with a patch against the `Modeling +framework` because it affects database schemas that have been created by the +framework v0.9pre16 or earlier versions. Worse, **it can lead to silent data +loss when used with postgresql and the ``psycopg`` python adaptor**. + +You'll find here a full description of the bug, along with instructions on how +existing database schemas can be fixed. + + +.. _`Modeling framework`: http://modeling.sourceforge.net + +.. contents:: + +Description of the bug +---------------------- + +Generation of the database schema sometimes produces foreign key constraints +that are invalid wrt the model. + +This happens when the model has a to-one relationship pointing to an +entity which has at least a sub-entity. Such a model:: + + model.version='0.1' + model.entities = [ # A-------- b -->B + Entity('A'), # / \ + Entity('B'), # /-+-\ + Entity('C', parent='B'), # | + ] # | + model.associations=[ # C + Association('A','B', relations=['b', 'as'] ), + ] + +generates a database schema which contains:: + + [...] + ALTER TABLE A ADD CONSTRAINT b FOREIGN KEY (FK_B) \ + REFERENCES B(ID) INITIALLY DEFERRED; + [...] + +This constraint is not valid, because an instance of ``A`` could reference +either a ``B`` or a ``C``. + +:Consequence: + Since some FK constraint is invalid, you will not be able to save changes in + an ``EditingContext`` when an ``A`` is in relation to a ``C``, just because + this violates the constraint. + + +Possible data loss with ``psycopg`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now if you use Postgresql and ``psycopg``, the problem is that this bug hits +an other bug in psycopg v1.1.10 or earlier, where errors at commit time are +silently ignored. As a consequence, if you save changes on an +``EditingContext`` which as an ``A`` in relation to a ``C``, the postgresql +database server will reject the commit (because of the buggy FK +constraint). But ``psycopg`` silently ignores the exception, as a consequence +**the changes appears to be safe but none of the changes was committed in the +database**. + +For this reason, it is strongly recommended to ``psycopg`` users to upgrade +their copy to v1.1.11 or higher + +For more details, please refer the corresponding thread in the `psycopg +archives +<http://lists.initd.org/pipermail/psycopg/2003-December/002432.html>`__. + +Fixing the database schema +-------------------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-15 09:44:16
|
Revision: 991 Author: sbigaret Date: 2006-04-15 02:43:57 -0700 (Sat, 15 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=991&view=rev Log Message: ----------- Development status is now Production/Stable Modified Paths: -------------- trunk/ProjectModeling/setup.py Modified: trunk/ProjectModeling/setup.py =================================================================== --- trunk/ProjectModeling/setup.py 2006-04-09 13:55:25 UTC (rev 990) +++ trunk/ProjectModeling/setup.py 2006-04-15 09:43:57 UTC (rev 991) @@ -35,7 +35,7 @@ # Instruction for PyPi found at: # http://www.python.org/~jeremy/weblog/030924.html classifiers = """\ -Development Status :: 4 - Beta +Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-09 13:55:34
|
Revision: 990 Author: sbigaret Date: 2006-04-09 06:55:25 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=990&view=rev Log Message: ----------- Fixed bug #621210: defining __cmp__ leads to infinite loop Modified Paths: -------------- trunk/ProjectModeling/Modeling/EditingContext.py Modified: trunk/ProjectModeling/Modeling/EditingContext.py =================================================================== --- trunk/ProjectModeling/Modeling/EditingContext.py 2006-04-09 13:54:25 UTC (rev 989) +++ trunk/ProjectModeling/Modeling/EditingContext.py 2006-04-09 13:55:25 UTC (rev 990) @@ -1340,7 +1340,10 @@ # We work for self, so we just remove the ones that are already # marked as deleted ec_deletedObjects = self.allDeletedObjects() - objects=[o for o in objects if o not in ec_deletedObjects] + objects=[o for o in objects + if id(o) not in [id(do) + for do in ec_deletedObjects] + ] else: # We're fetching raw rows. Wow, now we have to remove from the # list the dictionaries corresponding to the deleted objects. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-09 13:54:34
|
Revision: 989 Author: sbigaret Date: 2006-04-09 06:54:25 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=989&view=rev Log Message: ----------- Fixed bug #621210: defining __cmp__ leads to infinite loop Modified Paths: -------------- trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/__init__.py Modified: trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/__init__.py =================================================================== --- trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/__init__.py 2006-04-09 13:53:19 UTC (rev 988) +++ trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/__init__.py 2006-04-09 13:54:25 UTC (rev 989) @@ -2,6 +2,8 @@ from Modeling import ModelSet, Model +allow_cmp = 1 # part of the test for bug #621210 + if ModelSet.defaultModelSet().modelNamed("AuthorBooks") is None: import os mydir = os.path.abspath(os.path.dirname(__file__)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-04-09 13:53:33
|
Revision: 988 Author: sbigaret Date: 2006-04-09 06:53:19 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=988&view=rev Log Message: ----------- Fixed bug #621210: defining __cmp__ leads to infinite loop Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/DatabaseContext.py trunk/ProjectModeling/Modeling/RelationshipManipulation.py trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Book.py trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Writer.py trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-02-26 19:37:08 UTC (rev 987) +++ trunk/ProjectModeling/CHANGES 2006-04-09 13:53:19 UTC (rev 988) @@ -7,6 +7,12 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- + * Fixed bug #621210: when __cmp__ (and/or, possibly, other special methods + such as __eq__ or __ne__) was defined in a CustomObject, it was possible + to enter a infinite loop. The fix consisted in making sure that the + framework does not trigger those special methods, since in all cases what + we really want is comparing class instances by object identity. + 0.9 (2006/02/26) ---------------- Modified: trunk/ProjectModeling/Modeling/DatabaseContext.py =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseContext.py 2006-02-26 19:37:08 UTC (rev 987) +++ trunk/ProjectModeling/Modeling/DatabaseContext.py 2006-04-09 13:53:19 UTC (rev 988) @@ -1588,7 +1588,7 @@ aGlobalID -- KeyGlobalID (non temporary) """ - if anEditingContext.objectForGlobalID(aGlobalID)!=aDatabaseObject: + if id(anEditingContext.objectForGlobalID(aGlobalID))!=id(aDatabaseObject): raise ValueError, 'aDatabaseObject %s is not registered within the '\ 'EditingContext %s for globalID: %s'%(repr(aDatabaseObject), repr(anEditingContext), Modified: trunk/ProjectModeling/Modeling/RelationshipManipulation.py =================================================================== --- trunk/ProjectModeling/Modeling/RelationshipManipulation.py 2006-02-26 19:37:08 UTC (rev 987) +++ trunk/ProjectModeling/Modeling/RelationshipManipulation.py 2006-04-09 13:53:19 UTC (rev 988) @@ -77,7 +77,7 @@ # toOne relationship: is it already set? _backRelObj=anObject.valueForKey(_backRelKey) #if _backRelObj and _backRelObj.persistentID()!=self.persistentID(): - if _backRelObj and _backRelObj!=self: + if _backRelObj and id(_backRelObj)!=id(self): # Yes: now remove it _removeObjectFromBothSidesOfRelationshipWithKey(anObject, _backRelObj, _backRelKey, otoOnes, otoManys) _addObjectToPropertyWithKey(anObject, self, _backRelKey, otoOnes, otoManys) @@ -164,7 +164,7 @@ _removeObjectFromPropertyWithKey(self,anObject, aKey, toOnes, toManys) else: # toOne: check this is the one! - if self.valueForKey(aKey) != anObject: + if id(self.valueForKey(aKey)) != id(anObject): raise ValueError, 'anObject %s is not set for key %s'%(repr(anObject), aKey) _addObjectToPropertyWithKey(self,None, aKey, toOnes,toManys) @@ -205,7 +205,7 @@ if aKey in toOnes: # toOne: Simply uses KVC - if self.valueForKey(aKey)!=anObject: + if id(self.valueForKey(aKey)) != id(anObject): raise ValueError, 'anObject %s is not set for key %s'%(repr(anObject), aKey) self.takeValueForKey(None, aKey) Modified: trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Book.py =================================================================== --- trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Book.py 2006-02-26 19:37:08 UTC (rev 987) +++ trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Book.py 2006-04-09 13:53:19 UTC (rev 988) @@ -94,4 +94,26 @@ self.willChange() self._author=object + + def check_cmp_allowed(self): + # see comments in class Writer, same method + import AuthorBooks + from inspect import stack + if not AuthorBooks.allow_cmp and stack()[3][0].f_code.co_name not in ('__observersForObject', '__setObjectObservers', 'notifyObserversObjectWillChange','removeObjectFromAlreadyNotifiedObjects'): + raise 'Invalid call of %s in %s'%(stack()[1][0].f_code.co_name, + repr(self)) + + def __cmp__(self, o): + self.check_cmp_allowed() + return cmp( id(self), id(o) ) + + def __eq__(self, o): + self.check_cmp_allowed() + return id(self) == id(o) + def __ne__(self, o): + self.check_cmp_allowed() + return id(self) != id(o) + + def __hash__(self): + return hash(id(self)) Modified: trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Writer.py =================================================================== --- trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Writer.py 2006-02-26 19:37:08 UTC (rev 987) +++ trunk/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Writer.py 2006-04-09 13:53:19 UTC (rev 988) @@ -13,6 +13,7 @@ """ Writers are objects ... """ + allow_cmp=1 __implements__ = CustomObject.__implements__ @@ -137,18 +138,26 @@ def addToBooks(self,object): "Add the books relationship to many" + import AuthorBooks + _saved_value = AuthorBooks.allow_cmp + AuthorBooks.allow_cmp = 1 if object not in self._books: self.willChange() _books=list(self._books) _books.append(object) self._books=tuple(_books) + AuthorBooks.allow_cmp = _saved_value def removeFromBooks(self,object): "Remove the books relationship to many" self.willChange() _books=list(self._books) + import AuthorBooks + _saved_value = AuthorBooks.allow_cmp + AuthorBooks.allow_cmp = 1 _books.remove(object) self._books=tuple(_books) + AuthorBooks.allow_cmp = _saved_value @@ -164,3 +173,32 @@ def __str__(self): return '('+repr(self)+')'+' '+str(self._firstName)+' '+str(self._lastName) + + def check_cmp_allowed(self): + # part of the tests for bug #621210 + import AuthorBooks + from inspect import stack + + # excluded funcs are part of the Notification framework. It uses + # WeakDict. whose method get calls __cmp__ + # technically, these means that at some points, the framework does + # actually call __cmp__. for the moment we leave it as-is, since it + # is not triggering the infinite loop bug. + if not AuthorBooks.allow_cmp and stack()[3][0].f_code.co_name not in ('__observersForObject', '__setObjectObservers', 'notifyObserversObjectWillChange','removeObjectFromAlreadyNotifiedObjects'): + raise 'Invalid call of %s in %s'%(stack()[1][0].f_code.co_name, + repr(self)) + + def __cmp__(self, o): + self.check_cmp_allowed() + return cmp( id(self), id(o) ) + + def __eq__(self, o): + self.check_cmp_allowed() + return id(self) == id(o) + + def __ne__(self, o): + self.check_cmp_allowed() + return id(self) != id(o) + + def __hash__(self): + return hash(id(self)) Modified: trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py =================================================================== --- trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py 2006-02-26 19:37:08 UTC (rev 987) +++ trunk/ProjectModeling/Modeling/tests/test_EditingContext_Global.py 2006-04-09 13:53:19 UTC (rev 988) @@ -41,7 +41,6 @@ from AuthorBooks.Writer import Writer from AuthorBooks.Book import Book - from Modeling.EditingContext import EditingContext from Modeling.FetchSpecification import FetchSpecification from Modeling.Qualifier import qualifierWithQualifierFormat @@ -50,6 +49,18 @@ from Modeling import Adaptor from Modeling import Database +# The following is part of the global test for bug #621210 +# Note that the tests only works when using the testPackages/AuthorBooks +# modules, not the ones that are generated on the fly +# (see ref. to utils.dynamically_build_test_packages, above) +# The principle of the test is simple: the framework should not call any +# of the special funcs __cmp__ , __eq__, __ne__, etc. +import AuthorBooks +AuthorBooks.allow_cmp = 0 +def allow_cmp(): + AuthorBooks.allow_cmp = 1 +def forbid_cmp(): + AuthorBooks.allow_cmp = 0 class Writer_test07(Writer): refusesValidateForDelete=0 @@ -76,7 +87,6 @@ class TestEditingContext_Global(unittest.TestCase): "Global tests for EditingContext" - def test_00_insertObject_loads_databaseContexts(self): "[EditingContext] ..." # drop any existing default ObjectStoreCoordinator @@ -148,7 +158,9 @@ fetchSpec=FetchSpecification(entityName='Writer') objects=ec.objectsWithFetchSpecification(fetchSpec) + allow_cmp() self.failUnless(w in objects) + allow_cmp() def test_01c_objectsWithFetchSpecification_closes_adaptorChannel(self): "[EditingContext] objectsWithFetchSpecification closes adaptorChannel" @@ -170,10 +182,15 @@ objects_1=ec.objectsWithFetchSpecification(fetchSpec) objects_2=ec.fetch('Writer', 'lastName like "?a*"') self.failIf(len(objects_1)!=len(objects_2)) + allow_cmp() self.failIf([o for o in objects_1 if o not in objects_2]) + forbid_cmp() + objects_3=ec.fetch('Writer', qualifier) self.failIf(len(objects_1)!=len(objects_3)) + allow_cmp() self.failIf([o for o in objects_1 if o not in objects_3]) + forbid_cmp() def test_02_toOneFaultTrigger(self): "[EditingContext] toOneFaultTrigger" @@ -191,11 +208,12 @@ self.failUnless(dard_pygmalion.isFault()) dard_pygmalion.getLastName() #trigger self.failIf(dard_pygmalion.isFault()) + allow_cmp() self.failUnless(dard._pygmalion==dard_pygmalion) - # Last, check that the original object containing the toMany fault was not # marked as changed self.failIf(dard in ec.updatedObjects()) + forbid_cmp() self.failIf(ec.hasChanges()) def test_02b_toOneFaultOrNone(self): @@ -249,8 +267,10 @@ ec.processRecentChanges() self.failIf(ec.hasUnprocessedChanges(), 'no unprocessed changes anymore') self.failUnless(ec.hasChanges(), 'has changes') + allow_cmp() self.assertEqual(ec.insertedObjects(), [w]) - + forbid_cmp() + # new EC ec=EditingContext() fetchSpec=FetchSpecification(entityName='Writer') @@ -263,7 +283,9 @@ ec.processRecentChanges() self.failIf(ec.hasUnprocessedChanges(), 'no unprocessed changes anymore') self.failUnless(ec.hasChanges(), 'has changes') + allow_cmp() self.assertEqual(ec.updatedObjects(), [ws[0]]) + forbid_cmp() # new EC ec=EditingContext() @@ -299,11 +321,14 @@ dard_books=dard.getBooks() ldb=len(dard_books) # trigger dard_books=dard.getBooks() + allow_cmp() self.failIf(dard_books[0] in ec.deletedObjects()) + forbid_cmp() ec.processRecentChanges() self.failUnless(len(ec.deletedObjects())==ldb+1) # Check that the author was also deleted [cascade] + allow_cmp() self.failUnless(dard in ec.deletedObjects()) # AND that neither the author nor the book are marked as updated # [Bug #599602] @@ -312,6 +337,7 @@ for book in dard_books: self.failUnless(book in ec.deletedObjects()) + forbid_cmp() def test_06_deleteRule_nullify(self): "[EditingContext] processRecentChanges: deleteRule: NULLIFY" @@ -354,7 +380,9 @@ # Now the dard.getBooks() should have been refreshed and the book # that was deleted should be removed from dard's books. self.failIf(len(dard.getBooks())!=2) + allow_cmp() self.failIf(dard_book1 in dard.getBooks()) + forbid_cmp() def test_07_savechanges_01(self): @@ -447,8 +475,9 @@ ## return objects marked for deletion fetchSpec=FetchSpecification(entityName='Writer') writers=ec.objectsWithFetchSpecification(fetchSpec) + allow_cmp() self.failIf(hugo in writers) - + forbid_cmp() ## 4rd test: now deleting it for real should be OK hugo.refusesValidateForDelete=0 try: @@ -457,7 +486,9 @@ self.fail("Error: deletion failed") ## 5th test: check that the object has been removed from the uniquing table + allow_cmp() self.failIf(hugo in ec.registeredObjects()) + forbid_cmp() def test_09_savechanges_03(self): "[EditingContext] saveChanges part 03: change + validation" @@ -815,8 +846,10 @@ cleese.willChange() ec.setPropagatesInsertionForRelatedObjects(1) ec.processRecentChanges() + allow_cmp() self.failUnless(book_cleese in ec.insertedObjects()) self.failUnless(pygmalion_cleese in ec.insertedObjects()) + forbid_cmp() # Last: check that subsequent changes are notified after # ec.processRecentChanges() @@ -833,8 +866,10 @@ cleese.setPygmalion(pygmalion_cleese) cleese.addToBooks(book_cleese) ec.processRecentChanges() + allow_cmp() self.failUnless(book_cleese in ec.insertedObjects()) self.failUnless(pygmalion_cleese in ec.insertedObjects()) + forbid_cmp() def test_15_propagatesInsertionForRelatedObjects_02(self): "[EditingContext] propagatesInsertionForRelatedObjects (inserted objects)" @@ -849,13 +884,17 @@ hugo.addObjectToBothSidesOfRelationshipWithKey(b1, 'books') ec.processRecentChanges() + allow_cmp() self.failUnless(b1 in ec.insertedObjects()) + forbid_cmp() #Check that subsequent changes are notified after ec.processRecentChanges() b2=Book() ; b2.setTitle("Les travailleurs de la mer") hugo.addObjectToBothSidesOfRelationshipWithKey(b2, 'books') ec.processRecentChanges() + allow_cmp() self.failUnless(b2 in ec.insertedObjects()) + forbid_cmp() def test_16_toManySnapshotsUpdated(self): "[EditingContext] checks that toManySnapshots are correctly updated" @@ -1072,7 +1111,9 @@ self.assertEqual(adaptorChannel._count_for_execute, fetchCount+1) # fault was cleared for book in w.getBooks(): + allow_cmp() self.failIf(book not in tomany_fault) + forbid_cmp() def test_21_snapshot_raw(self): "[EditingContext] CustomObject.snapshot_raw()" @@ -1139,23 +1180,36 @@ ec=EditingContext() rabelais=ec.fetch('Writer', 'lastName == "Rabelais"')[0] ec.deleteObject(rabelais) + allow_cmp() self.failUnless(rabelais in ec.allDeletedObjects()) self.failIf(rabelais in ec.deletedObjects()) # unprocessed + forbid_cmp() ec.insertObject(rabelais) # cancel the deletion self.failIf(len(ec.fetch('Writer', 'lastName == "Rabelais"'))!=1) + allow_cmp() self.failIf(rabelais in ec.allDeletedObjects()) self.failIf(rabelais in ec.allInsertedObjects()) - + forbid_cmp() + ## check: delete / processRecentChanges / insert ec=EditingContext() rabelais=ec.fetch('Writer', 'lastName == "Rabelais"')[0] ec.deleteObject(rabelais) + allow_cmp() self.failUnless(rabelais in ec.allDeletedObjects()) + forbid_cmp() + ec.processRecentChanges() + + allow_cmp() self.failUnless(rabelais in ec.deletedObjects()) + forbid_cmp() + ec.insertObject(rabelais) # cancel the deletion + allow_cmp() self.failIf(rabelais in ec.allDeletedObjects()) self.failIf(rabelais in ec.allInsertedObjects()) + forbid_cmp() ## check: delete / saveChanges / insert ec=EditingContext() @@ -1167,12 +1221,16 @@ new=ec.fetch('Writer', 'lastName == "test_22"')[0] new_gid=new.globalID() ec.deleteObject(new) + allow_cmp() self.failUnless(new in ec.allDeletedObjects()) self.failIf(new in ec.deletedObjects()) + forbid_cmp() ec.saveChanges() ec.insertObject(new) # cancel the deletion? No, insertion of a new object + allow_cmp() self.failIf(new in ec.allDeletedObjects()) self.failUnless(new in ec.allInsertedObjects()) + forbid_cmp() self.failIf(new.globalID()==new_gid) self.failIf(not new.globalID().isTemporary()) @@ -1186,18 +1244,32 @@ new=ec.fetch('Writer', 'lastName == "test_22"')[0] new_gid=new.globalID() new.setLastName('test_22 alternate value') + allow_cmp() self.failUnless(new in ec.allUpdatedObjects()) + forbid_cmp() + ec.deleteObject(new) + + allow_cmp() self.failUnless(new in ec.allDeletedObjects()) self.failIf(new in ec.deletedObjects()) self.failIf(new in ec.allUpdatedObjects()) + forbid_cmp() + ec.processRecentChanges() + + allow_cmp() self.failUnless(new in ec.deletedObjects()) self.failIf(new in ec.allUpdatedObjects()) + forbid_cmp() + ec.insertObject(new) # cancel the deletion + + allow_cmp() self.failIf(new in ec.allDeletedObjects()) self.failUnless(new in ec.allUpdatedObjects()) self.failUnless(new.globalID()==new_gid) + forbid_cmp() ## check: modify / delete / saveChanges / insert @@ -1262,8 +1334,10 @@ # explicitely look for duplicates for w in ws: _ws=list(ws) #[:-1]) + allow_cmp() _ws.remove(w) self.failIf(w in _ws, 'Duplicate found: %s'%w) + forbid_cmp() def test_25_fetchCount_is_not_affected_by_duplicates(self): "[EditingContext] fetchCount is not affected by duplicates" @@ -1320,6 +1394,47 @@ self.failUnless(len(objects)==1) self.failUnless('Dard' in objects_names) + def test_29_bug621210(self): + "[EditingContext] Infinite loop when defining __cmp__" + # Note: bug #621210 is in fact tested not only w/ this test, but also + # globally. See notes at the beginning of this file, and changes + # introduced in revision 988. + ec=EditingContext() + from new import instancemethod + def invalid_call_fct(msg): + def invalid_call(self, o, msg): + raise 'Invalid call of %s in %s'%(msg,self) + return lambda s,o,fct=invalid_call,msg=msg: fct(s,o,msg) + Writer.__cmp__ = instancemethod(invalid_call_fct('__cmp__'), None, Writer) + Writer.__eq__ = instancemethod(invalid_call_fct('__eq__'), None, Writer) + Writer.__ne__ = instancemethod(invalid_call_fct('__ne__'), None, Writer) + + gargantua=ec.fetch('Book', 'title == "Gargantua"')[0] + rabelais = gargantua.getAuthor() + self.failUnless(rabelais.isFault()) + rabelais.getLastName() + + def _test_29_fetch_backslash(self): + "[EditingContext] fetch real backslash" + # bug # + ec=EditingContext() + b1=Book(); b1.setTitle(r'abc\n') + b2=Book(); b2.setTitle('abc\\\\') + b3=Book(); b3.setTitle('\\') + ec.insert(b1); ec.insert(b2); ec.insert(b3) + ec.saveChanges() + + res=ec.fetch('Book', 'title == "abc\\n"') + self.assertEqual(len(res), 1) + self.assertEqual(res[0].getTitle(), r"abc\n") + res=ec.fetch('Book', 'title == "\\"') + self.assertEqual(len(res), 1) + self.assertEqual(res[0].getTitle(), "\\") + #res=ec.fetch('Book', 'title like "*abc%d*"') + #self.assertEqual(len(res), 1) + #self.assertEqual(res[0].getTitle(), "abc%d") + # TBD: with LIKE and ILIKE + def test_999_customSQLQuery(self): "[EditingContext] custom SQL Query" fs=FetchSpecification(entityName='Writer') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 19:37:24
|
Revision: 987 Author: sbigaret Date: 2006-02-26 11:37:08 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=987&view=rev Log Message: ----------- Release 0.9 Added Paths: ----------- tags/release-0.9/ZModeling/ Copied: tags/release-0.9/ZModeling (from rev 986, trunk/ZModeling) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 19:22:41
|
Revision: 985 Author: sbigaret Date: 2006-02-26 11:22:29 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=985&view=rev Log Message: ----------- Release 0.9 Added Paths: ----------- tags/release-0.9/ Copied: tags/release-0.9 (from rev 984, trunk/ProjectModeling) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 18:38:21
|
Revision: 984 Author: sbigaret Date: 2006-02-26 10:38:13 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=984&view=rev Log Message: ----------- Added reference to file tests/test.sh Modified Paths: -------------- trunk/ProjectModeling/MANIFEST.in Modified: trunk/ProjectModeling/MANIFEST.in =================================================================== --- trunk/ProjectModeling/MANIFEST.in 2006-02-26 18:28:43 UTC (rev 983) +++ trunk/ProjectModeling/MANIFEST.in 2006-02-26 18:38:13 UTC (rev 984) @@ -16,6 +16,7 @@ include Modeling/tests/MySQL.cfg include Modeling/tests/SQLite.cfg include Modeling/tests/Oracle.cfg +include Modeling/tests/tests.sh recursive-include Modeling/tests/xmlmodels *.txt *.xml *.py This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 18:28:56
|
Revision: 983 Author: sbigaret Date: 2006-02-26 10:28:43 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=983&view=rev Log Message: ----------- Fixed MANIFEST Modified Paths: -------------- trunk/ProjectModeling/MANIFEST.in Added Paths: ----------- trunk/ProjectModeling/Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/LICENSE Modified: trunk/ProjectModeling/MANIFEST.in =================================================================== --- trunk/ProjectModeling/MANIFEST.in 2006-02-26 18:15:28 UTC (rev 982) +++ trunk/ProjectModeling/MANIFEST.in 2006-02-26 18:28:43 UTC (rev 983) @@ -1,8 +1,8 @@ -include COPYING +include LICENSE include INSTALL include MIGRATION include TODO -include Modeling/COPYING +include Modeling/LICENSE include Modeling/TODO include Modeling/scripts/mdl_generate_DB_schema.py @@ -19,32 +19,32 @@ recursive-include Modeling/tests/xmlmodels *.txt *.xml *.py -include Modeling/DatabaseAdaptors/COPYING +include Modeling/DatabaseAdaptors/LICENSE include Modeling/DatabaseAdaptors/CHANGES include Modeling/DatabaseAdaptors/README include Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/CHANGES -include Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/COPYING +include Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/LICENSE include Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/README include Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/TODO -include Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/COPYING +include Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/LICENSE include Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/CHANGES include Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/DEPENDENCIES include Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/INSTALL include Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/TODO -include Modeling/DatabaseAdaptors/MySQLAdaptorLayer/COPYING +include Modeling/DatabaseAdaptors/MySQLAdaptorLayer/LICENSE include Modeling/DatabaseAdaptors/MySQLAdaptorLayer/CHANGES include Modeling/DatabaseAdaptors/MySQLAdaptorLayer/DEPENDENCIES include Modeling/DatabaseAdaptors/MySQLAdaptorLayer/README include Modeling/DatabaseAdaptors/MySQLAdaptorLayer/TODO -include Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/COPYING +include Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/LICENSE include Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/README.txt include Modeling/DatabaseAdaptors/SQLiteAdaptorLayer/TODO -include Modeling/DatabaseAdaptors/OracleAdaptorLayer/COPYING +include Modeling/DatabaseAdaptors/OracleAdaptorLayer/LICENSE recursive-include Modeling/ModelMasons *.tmpl *.gif Added: trunk/ProjectModeling/Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/LICENSE =================================================================== --- trunk/ProjectModeling/Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/LICENSE (rev 0) +++ trunk/ProjectModeling/Modeling/DatabaseAdaptors/AbstractDBAPI2AdaptorLayer/LICENSE 2006-02-26 18:28:43 UTC (rev 983) @@ -0,0 +1,31 @@ +Modeling Framework: an Object-Relational Bridge for python + +Copyright (c) 2001 - 2006 Sstien Bigaret <sbi...@us...> +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of its copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 18:15:35
|
Revision: 982 Author: sbigaret Date: 2006-02-26 10:15:28 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=982&view=rev Log Message: ----------- release 0.9 Modified Paths: -------------- trunk/ProjectModeling/CHANGES Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-02-26 18:12:56 UTC (rev 981) +++ trunk/ProjectModeling/CHANGES 2006-02-26 18:15:28 UTC (rev 982) @@ -7,6 +7,9 @@ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- +0.9 (2006/02/26) +---------------- + * Now distributed under a 3-clause BSD-style license, see LICENSE for details * Fixed bug #918115: tests were failing under py2.1 w/ ZODB was installed, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 18:13:15
|
Revision: 981 Author: sbigaret Date: 2006-02-26 10:12:56 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=981&view=rev Log Message: ----------- Preparation for v0.9 Modified Paths: -------------- trunk/ProjectModeling/CHANGES trunk/ProjectModeling/Modeling/__init__.py trunk/ProjectModeling/Modeling/doc/HomePage/downloads.tex trunk/ProjectModeling/Modeling/doc/HomePage/main.tex trunk/ProjectModeling/Modeling/doc/Tutorial.tex trunk/ProjectModeling/Modeling/doc/UserGuide.tex trunk/ProjectModeling/setup.py trunk/ProjectModeling/vertoo.data Modified: trunk/ProjectModeling/CHANGES =================================================================== --- trunk/ProjectModeling/CHANGES 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/CHANGES 2006-02-26 18:12:56 UTC (rev 981) @@ -2,7 +2,7 @@ Module Modeling --------------- -Current release is: 0.9-pre-17.1 / See also: TODO, INSTALL and doc/ +Current release is: 0.9 / See also: TODO, INSTALL and doc/ ** Distributed under a 3-clause BSD-style license, see LICENSE for details ** ----------------------------------------------------------------------------- Modified: trunk/ProjectModeling/Modeling/__init__.py =================================================================== --- trunk/ProjectModeling/Modeling/__init__.py 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/Modeling/__init__.py 2006-02-26 18:12:56 UTC (rev 981) @@ -25,7 +25,7 @@ SQLite. """ -__version__="0.9-pre-17.1" +__version__="0.9" import DatabaseContext # make it register itself for notifications from utils import migration_warnings Modified: trunk/ProjectModeling/Modeling/doc/HomePage/downloads.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/HomePage/downloads.tex 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/Modeling/doc/HomePage/downloads.tex 2006-02-26 18:12:56 UTC (rev 981) @@ -9,7 +9,7 @@ \maketitle \begin{enumerate} -\item[\bf Current version: 0.9-pre-17.1] +\item[\bf Current version: 0.9] Download it here:\begin{rawhtml}<a href="https://sourceforge.net/projects/modeling/">Sourceforge's project home Modified: trunk/ProjectModeling/Modeling/doc/HomePage/main.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/HomePage/main.tex 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/Modeling/doc/HomePage/main.tex 2006-02-26 18:12:56 UTC (rev 981) @@ -6,7 +6,7 @@ % Increment the release number whenever significant changes are made. % The author and/or editor can define 'significant' however they like. -%\release{0.9-pre-17.1} +%\release{0.9} % At minimum, give your name and an email address. You can include a % snail-mail address if you like. Modified: trunk/ProjectModeling/Modeling/doc/Tutorial.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/Tutorial.tex 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/Modeling/doc/Tutorial.tex 2006-02-26 18:12:56 UTC (rev 981) @@ -13,7 +13,7 @@ \authoraddress{Email: \email{sbi...@us...}} \date{February 10, 2003} %\date{\today} -\release{0.9-pre-17.1} +\release{0.9} %\setreleaseinfo{5} \setshortversion{0.9} Modified: trunk/ProjectModeling/Modeling/doc/UserGuide.tex =================================================================== --- trunk/ProjectModeling/Modeling/doc/UserGuide.tex 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/Modeling/doc/UserGuide.tex 2006-02-26 18:12:56 UTC (rev 981) @@ -21,9 +21,9 @@ % Please at least include a long-lived email address; % the rest is at your discretion. \authoraddress{Email: \email{sbi...@us...}} -%\date{Feb 22, 2004} +%\date{Feb 26, 2006} \date{\today} -\release{0.9-pre-17.1} +\release{0.9} %\setreleaseinfo{pre-8} \setshortversion{0.9} Modified: trunk/ProjectModeling/setup.py =================================================================== --- trunk/ProjectModeling/setup.py 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/setup.py 2006-02-26 18:12:56 UTC (rev 981) @@ -70,7 +70,7 @@ compile_cheetah_template(cheetah_compile_cmd) setup(name="ModelingCore", - version="0.9-pre-17.1", + version="0.9", license ="BSD License", description=short_description, author="Sstien Bigaret", Modified: trunk/ProjectModeling/vertoo.data =================================================================== --- trunk/ProjectModeling/vertoo.data 2006-02-26 18:04:47 UTC (rev 980) +++ trunk/ProjectModeling/vertoo.data 2006-02-26 18:12:56 UTC (rev 981) @@ -1,2 +1,2 @@ -mdl-code = major:0; minor:9; pre:17.1; release:x; date:Feb 22, 2004; -mdl_doc = major:0; minor:9; pre:17.1; release:x; date:Feb 22, 2004; \ No newline at end of file +mdl-code = major:0; minor:9; pre:x; release:x; date:Feb 26, 2006; +mdl_doc = major:0; minor:9; pre:x; release:x; date:Feb 26, 2006; \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 18:04:55
|
Revision: 980 Author: sbigaret Date: 2006-02-26 10:04:47 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=980&view=rev Log Message: ----------- 2nd part of the fix for bug #918115 Modified Paths: -------------- trunk/ProjectModeling/Modeling/utils.py Modified: trunk/ProjectModeling/Modeling/utils.py =================================================================== --- trunk/ProjectModeling/Modeling/utils.py 2006-02-26 17:50:55 UTC (rev 979) +++ trunk/ProjectModeling/Modeling/utils.py 2006-02-26 18:04:47 UTC (rev 980) @@ -202,6 +202,10 @@ substituting the method with a lambda returning the value the original method returned. + This method does nothing under python v2.1 if ZODB is found in the path, + because it is incompatible with the extension class, used by classes Entity, + Relationship, etc. + Parameters: anInstance -- the instance to examine @@ -210,9 +214,14 @@ See also: methods_to_cache() """ - import os + import os, sys if not os.environ.get('MDL_ENABLE_SIMPLE_METHOD_CACHE', None): return + + if sys.version_info < (2,2): + import warnings + warnings.warn("Cannot cache methods on py2.1 when ZODB is in the python path", RuntimeWarning) + return from new import instancemethod for m in methods_to_cache(anInstance.__class__, exclude): try: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sbi...@us...> - 2006-02-26 17:51:02
|
Revision: 979 Author: sbigaret Date: 2006-02-26 09:50:55 -0800 (Sun, 26 Feb 2006) ViewCVS: http://svn.sourceforge.net/modeling/?rev=979&view=rev Log Message: ----------- Updated; uses py2.4 Modified Paths: -------------- trunk/ProjectModeling/Modeling/tests/test_generate_python_code.sh Modified: trunk/ProjectModeling/Modeling/tests/test_generate_python_code.sh =================================================================== --- trunk/ProjectModeling/Modeling/tests/test_generate_python_code.sh 2006-02-26 17:50:15 UTC (rev 978) +++ trunk/ProjectModeling/Modeling/tests/test_generate_python_code.sh 2006-02-26 17:50:55 UTC (rev 979) @@ -3,7 +3,7 @@ ## See also xmlmodels/README.txt GENERATE=../scripts/mdl_generate_python_code.py RMDIR='/bin/rm -rf' -PYTHON=python2.2 +PYTHON=python2.4 tests_dir=`pwd` mdl_dir=`dirname $tests_dir` @@ -84,7 +84,7 @@ } function generate() { - execute $PYTHON $GENERATE $* + execute $PYTHON $GENERATE -f $* } ## Save the original testPackages directories This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |