From vernondcole at gmail.com Mon Feb 2 17:34:43 2009 From: vernondcole at gmail.com (Vernon Cole) Date: Mon, 2 Feb 2009 09:34:43 -0700 Subject: [DB-SIG] PEP 249 .Binary() function incorrect for Python 3.0 ? Message-ID: Hello, everyone: Work has gone well in porting adodbapi to work in Python 3.0. The result should be posted in a beta version in pywin32 v.213 real soon now. I have patched the standards compliance test as discussed earlier in this forum. There is one last error I am getting, but I believe that should be left intact, as a protection when porting to 3.0. The PEP says: > > Binary(string) > > This function constructs an object capable of holding a > binary (long) string value. Given that Python 3.0 no longer uses a string for this purpose, the routine should really accept an object of data type "byte". My 3.0 ready code looks like this: > if sys.version[0] == '3': > makeByteBuffer = bytes > else: > makeByteBuffer = buffer def Binary(aString): > """This function constructs an object capable of holding a binary > (long) string value. """ > return makeByteBuffer(aString) The python 3.0 built in function "bytes" insists that, if it is fed a unicode string, it must also have an encoding. So when I run the compliance test, I get: > C:\adodbapi_225\adodbapi30\tests>test_adodbapi_dbapi20.py > This module depends on the dbapi20 compliance tests created by Stuart > Bishop > (see db-sig mailing list history for info) > adodbapi v2.2.5 > Tested with dbapi20 1.1.1.1.2.1 > ...Testing MS-SQL login... > ..E................................. > ====================================================================== > ERROR: test_Binary (__main__.test_adodbapi) > ---------------------------------------------------------------------- > Traceback (most recent call last): > File "C:\adodbapi_225\adodbapi30\tests\dbapi20.py", line 835, in > test_Binary > b = self.driver.Binary('Something') > File "C:\adodbapi_225\adodbapi30\adodbapi.py", line 972, in Binary > return makeByteBuffer(aString) > TypeError: string argument without an encoding > > ---------------------------------------------------------------------- > Ran 36 tests in 14.208s > > FAILED (errors=1) > IMHO, in Python 3.0, this is exactly what should happen, so that the programmer will be aware that the interface has changed. What do you all think? -- Vernon Cole -------------- next part -------------- An HTML attachment was scrubbed... URL: From mal at egenix.com Mon Feb 2 18:01:21 2009 From: mal at egenix.com (M.-A. Lemburg) Date: Mon, 02 Feb 2009 18:01:21 +0100 Subject: [DB-SIG] PEP 249 .Binary() function incorrect for Python 3.0 ? In-Reply-To: References: Message-ID: <498726E1.6020008@egenix.com> On 2009-02-02 17:34, Vernon Cole wrote: > Hello, everyone: > > Work has gone well in porting adodbapi to work in Python 3.0. The result > should be posted in a beta version in pywin32 v.213 real soon now. > I have patched the standards compliance test as discussed earlier in this > forum. > There is one last error I am getting, but I believe that should be left > intact, as a protection when porting to 3.0. > > The PEP says: >> Binary(string) >> >> This function constructs an object capable of holding a >> binary (long) string value. > > Given that Python 3.0 no longer uses a string for this purpose, the routine > should really accept an object of data type "byte". That's not entirely correct: the return type of Binary() is not defined by the spec, only the fact that a binary string must be acceptable as input type. In Python 2, this is str(), in Python 3, bytes(). The output type of Binary() is module specific, since different modules may need different types. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Feb 02 2009) >>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ ________________________________________________________________________ ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ From vernondcole at gmail.com Mon Feb 2 23:59:53 2009 From: vernondcole at gmail.com (Vernon Cole) Date: Mon, 2 Feb 2009 15:59:53 -0700 Subject: [DB-SIG] PEP 249 .Binary() function incorrect for Python 3.0 ? In-Reply-To: <498726E1.6020008@egenix.com> References: <498726E1.6020008@egenix.com> Message-ID: Marc-Andre; So, to clarify: You are saying that it is acceptable for a Python 3.0 implementation to raise an error when .Binary() receives a unicode string. It should expect a b'xxx binary string here xxx' type. Is that correct? -- Vernon On Mon, Feb 2, 2009 at 10:01 AM, M.-A. Lemburg wrote: > On 2009-02-02 17:34, Vernon Cole wrote: > > Hello, everyone: > > > > Work has gone well in porting adodbapi to work in Python 3.0. The result > > should be posted in a beta version in pywin32 v.213 real soon now. > > I have patched the standards compliance test as discussed earlier in this > > forum. > > There is one last error I am getting, but I believe that should be left > > intact, as a protection when porting to 3.0. > > > > The PEP says: > >> Binary(string) > >> > >> This function constructs an object capable of holding a > >> binary (long) string value. > > > > Given that Python 3.0 no longer uses a string for this purpose, the > routine > > should really accept an object of data type "byte". > > That's not entirely correct: the return type of Binary() is not defined > by the spec, only the fact that a binary string must be acceptable as > input type. In Python 2, this is str(), in Python 3, bytes(). > > The output type of Binary() is module specific, since different modules > may need different types. > > -- > Marc-Andre Lemburg > eGenix.com > > Professional Python Services directly from the Source (#1, Feb 02 2009) > >>> Python/Zope Consulting and Support ... http://www.egenix.com/ > >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ > >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ > ________________________________________________________________________ > > ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: > > > eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 > D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg > Registered at Amtsgericht Duesseldorf: HRB 46611 > http://www.egenix.com/company/contact/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mal at egenix.com Tue Feb 3 14:30:22 2009 From: mal at egenix.com (M.-A. Lemburg) Date: Tue, 03 Feb 2009 14:30:22 +0100 Subject: [DB-SIG] PEP 249 .Binary() function incorrect for Python 3.0 ? In-Reply-To: References: <498726E1.6020008@egenix.com> Message-ID: <498846EE.2020709@egenix.com> On 2009-02-02 23:59, Vernon Cole wrote: > Marc-Andre; > So, to clarify: You are saying that it is acceptable for a Python 3.0 > implementation > to raise an error when .Binary() receives a unicode string. It should > expect a b'xxx binary string here xxx' type. > Is that correct? Again, that's up to the constructor. It could e.g. accept Unicode if it's all ASCII or contains a hex/base64 representation of the binary data. However, it certainly makes sense to just alias Binary to the bytes type constructor for simplicity. > -- > Vernon > > On Mon, Feb 2, 2009 at 10:01 AM, M.-A. Lemburg wrote: > >> On 2009-02-02 17:34, Vernon Cole wrote: >>> Hello, everyone: >>> >>> Work has gone well in porting adodbapi to work in Python 3.0. The result >>> should be posted in a beta version in pywin32 v.213 real soon now. >>> I have patched the standards compliance test as discussed earlier in this >>> forum. >>> There is one last error I am getting, but I believe that should be left >>> intact, as a protection when porting to 3.0. >>> >>> The PEP says: >>>> Binary(string) >>>> >>>> This function constructs an object capable of holding a >>>> binary (long) string value. >>> Given that Python 3.0 no longer uses a string for this purpose, the >> routine >>> should really accept an object of data type "byte". >> That's not entirely correct: the return type of Binary() is not defined >> by the spec, only the fact that a binary string must be acceptable as >> input type. In Python 2, this is str(), in Python 3, bytes(). >> >> The output type of Binary() is module specific, since different modules >> may need different types. >> >> -- >> Marc-Andre Lemburg >> eGenix.com >> >> Professional Python Services directly from the Source (#1, Feb 02 2009) >>>>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>>>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ >> ________________________________________________________________________ >> >> ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: >> >> >> eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 >> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg >> Registered at Amtsgericht Duesseldorf: HRB 46611 >> http://www.egenix.com/company/contact/ >> > > > ------------------------------------------------------------------------ > > _______________________________________________ > DB-SIG maillist - DB-SIG at python.org > http://mail.python.org/mailman/listinfo/db-sig -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Feb 03 2009) >>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ ________________________________________________________________________ ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ From wtr_web at wtresearch.de Wed Feb 4 20:19:52 2009 From: wtr_web at wtresearch.de (wtr_web) Date: Wed, 4 Feb 2009 20:19:52 +0100 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: References: Message-ID: Hello! I need to access a SQLServer 2005 by creating, reading and writing by a single thread/single user. Has anybody experience with some openSrc SW? There are quite large amounts of data involved (around a million rows in some tables). I have only used Oracle-access myself. Thank you! wolfgang teschner From mal at egenix.com Wed Feb 4 21:59:21 2009 From: mal at egenix.com (M.-A. Lemburg) Date: Wed, 04 Feb 2009 21:59:21 +0100 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: References: Message-ID: <498A01A9.5000502@egenix.com> On 2009-02-04 20:19, wtr_web wrote: > Hello! > I need to access a SQLServer 2005 by creating, reading and writing by a > single thread/single user. > Has anybody experience with some openSrc SW? There are quite large > amounts of data involved (around a million > rows in some tables). > I have only used Oracle-access myself. mxODBC will allow you to access SQL Server 2005 without problems, from Windows and Unix: http://www.egenix.com/products/python/mxODBC/ If your client application runs on Linux, Mac OS X or other more exotic platforms, you may also want to have a look at mxODBC Connect, which uses a client-server approach to database connectivity: http://www.egenix.com/products/python/mxODBCConnect/ -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Feb 04 2009) >>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ ________________________________________________________________________ ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ From uwemailmeister at googlemail.com Wed Feb 4 22:14:13 2009 From: uwemailmeister at googlemail.com (Uwe Grauer) Date: Wed, 04 Feb 2009 22:14:13 +0100 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: References: Message-ID: <498A0525.5080700@googlemail.com> wtr_web wrote: > Hello! > I need to access a SQLServer 2005 by creating, reading and writing by a > single thread/single user. > Has anybody experience with some openSrc SW? There are quite large > amounts of data involved (around a million > rows in some tables). > I have only used Oracle-access myself. pymssql 1.0.0 was released a few days ago: http://pymssql.sourceforge.net/ Uwe From fumanchu at aminus.org Wed Feb 4 23:00:12 2009 From: fumanchu at aminus.org (Robert Brewer) Date: Wed, 4 Feb 2009 14:00:12 -0800 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: References: Message-ID: wtr_web wrote: > I need to access a SQLServer 2005 by creating, reading and writing by > a single thread/single user. > Has anybody experience with some openSrc SW? There are quite large > amounts of data involved (around a million rows in some tables). > I have only used Oracle-access myself. http://www.aminus.net/geniusql can do that. To create a SQL Server 2005 database: >>> db = geniusql.db("sqlserver", **{ "name": 'demo', 'connections.Connect': "Provider=SQLNCLI; Integrated Security=SSPI; Initial Catalog=demo; Data Source=(local)\VAIO_VEDB"}) >>> db.create() >>> s = db.schema() >>> s.create() >>> s.name 'dbo' Now add a table: >>> Animal = s.table('Animal') >>> Animal['ID'] = s.column(int, autoincrement=True, key=True) >>> Animal['Name'] = s.column(unicode) >>> Animal['Legs'] = s.column(int, default=4) >>> s['Animal'] = Animal >>> s.items() [('Animal', geniusql.providers.sqlserver.SQLServerTable('Animal', '[Animal]'))] >>> s['Animal'] geniusql.providers.sqlserver.SQLServerTable('Animal', '[Animal]') >>> s['Animal']['Name'] geniusql.objects.Column(, geniusql.providers.sqlserver.VARCHAR(_bytes=255), default=None, key=False, name='Name', qname='[Name]') ...and insert some rows: >>> Animal.insert(Name="Gorilla", Legs=2) {'Legs': 2, 'Name': 'Gorilla', 'ID': 1} >>> Animal.insert(Name="Fox") {'Name': 'Fox', 'ID': 2} >>> Animal.insert(Name="Bear") {'Name': 'Bear', 'ID': 3} >>> Animal.select_all(Legs=4) [{'Legs': 4, 'ID': 2, 'Name': u'Fox'}, {'Legs': 4, 'ID': 3, 'Name': u'Bear'}] Now let's close our first connection and reconnect: >>> db.connections.shutdown() >>> del s >>> db = geniusql.db("sqlserver", **{ "name": 'demo', 'connections.Connect': "Provider=SQLNCLI; Integrated Security=SSPI; Initial Catalog=demo; Data Source=(local)\VAIO_VEDB"}) >>> s = db.schema("dbo") >>> s.discover_all() >>> s.items() [('Animal', geniusql.providers.sqlserver.SQLServerTable('Animal', '[Animal]'))] >>> s['Animal'].select_all(Legs=4) [{'Legs': 4, 'ID': 2, 'Name': 'Fox'}, {'Legs': 4, 'ID': 3, 'Name': 'Bear'}] By default, db.connections uses a pool of connections; any thread that needs a new connection checks one out of the pool: >>> db.connections._factory However, there are other available factories: * ConnectionPerThread: makes a new conn for each thread * SingleConnection: makes a new conn per process (shared by all threads) * ConnectionFactory: makes a new conn per query/statement Example: >>> db.connections._factory = geniusql.conns.ConnectionPerThread( db.connections._get_conn, db.connections._del_conn) >>> Animal.select_all(Legs=4) [{'Legs': 4, 'ID': 2, 'Name': u'Fox'}, {'Legs': 4, 'ID': 3, 'Name': u'Bear'}] Robert Brewer fumanchu at aminus.org From bkline at rksystems.com Thu Feb 5 05:03:12 2009 From: bkline at rksystems.com (Bob Kline) Date: Wed, 04 Feb 2009 23:03:12 -0500 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: <498A0525.5080700@googlemail.com> References: <498A0525.5080700@googlemail.com> Message-ID: <498A6500.90207@rksystems.com> Uwe Grauer wrote: > pymssql 1.0.0 was released a few days ago: > http://pymssql.sourceforge.net/ > Despite it's version number, it might not be ready for prime time yet. I pulled it down to try it out, and this is what I got back from my first attempt to feed it an SQL statement: >>> cursor.execute("create table t (i int primary key, n varchar(32))") Traceback (most recent call last): File "", line 1, in File "pymssql.py", line 182, in execute self._source.execute_query(operation, params) TypeError: not all arguments converted during string formatting -- Bob Kline http://www.rksystems.com mailto:bkline at rksystems.com From szybalski at gmail.com Thu Feb 5 06:25:11 2009 From: szybalski at gmail.com (Lukasz Szybalski) Date: Wed, 4 Feb 2009 23:25:11 -0600 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: References: Message-ID: <804e5c70902042125w5aa5930bq9cbd4865926abd21@mail.gmail.com> On Wed, Feb 4, 2009 at 1:19 PM, wtr_web wrote: > Hello! > I need to access a SQLServer 2005 by creating, reading and writing by a > single thread/single user. > Has anybody experience with some openSrc SW? There are quite large amounts > of data involved (around a million > rows in some tables). > I have only used Oracle-access myself. open source: (works on all linux,windows, should work on mac but I have not tried it) pyodbc, ceodbc (http://lucasmanual.com/mywiki/PythonManual#head-0bda5a45da288aa375abc15836781703923a6a3f ) sqlalchemy (which uses pyodbc or pymssql) Lucas > > Thank you! > > wolfgang teschner > _______________________________________________ > DB-SIG maillist - DB-SIG at python.org > http://mail.python.org/mailman/listinfo/db-sig > -- How to create python package? http://lucasmanual.com/mywiki/PythonPaste Bazaar and Launchpad http://lucasmanual.com/mywiki/Bazaar From vernondcole at gmail.com Thu Feb 5 16:59:08 2009 From: vernondcole at gmail.com (Vernon Cole) Date: Thu, 5 Feb 2009 08:59:08 -0700 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: <804e5c70902042125w5aa5930bq9cbd4865926abd21@mail.gmail.com> References: <804e5c70902042125w5aa5930bq9cbd4865926abd21@mail.gmail.com> Message-ID: If you are running on Windows, you really owe it to yourself to use pywin32 for many reasons. https://sourceforge.net/project/platformdownload.php?group_id=78018 Both odbc (using dbapi version 1.0) and adodbapi (using dbapi version 2.0) are included. This is a free and open source project. -- Vernon Cole -------------- next part -------------- An HTML attachment was scrubbed... URL: From fabien.coutant at neuf.fr Thu Feb 5 18:42:09 2009 From: fabien.coutant at neuf.fr (Fabien COUTANT) Date: Thu, 5 Feb 2009 18:42:09 +0100 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: References: Message-ID: <20090205184209.60e09536.fabien.coutant@neuf.fr> Le Wed, 04 Feb 2009 20:19:52 +0100, wtr_web a ?crit: > Hello! > I need to access a SQLServer 2005 by creating, reading and writing by > a single thread/single user. > Has anybody experience with some openSrc SW? There are quite large > amounts of data involved (around a million > rows in some tables). > I have only used Oracle-access myself. Hello, AFAIK SQLServer speaks the same "TDS" protocol as Sybase (which it originated from long ago). So you could try FreeTDS which is a C-level lib to speak this protocol: http://www.freetds.org/ and especially http://www.freetds.org/userguide/python.htm with a corresponding Python binding of this library: http://python-sybase.sourceforge.net/ (replaces the old http://object-craft.com.au/projects/sybase/index.html ) (maybe there are other bindings, didn't look further) FreeTDS is explicitly reporting to work with MS SQL Server, including recent versions. And it seems much more mature and stable than pymssql... -- Hope this helps, Fabien. From mal at egenix.com Thu Feb 5 21:50:46 2009 From: mal at egenix.com (M.-A. Lemburg) Date: Thu, 05 Feb 2009 21:50:46 +0100 Subject: [DB-SIG] SQLServer 2005 In-Reply-To: <20090205184209.60e09536.fabien.coutant@neuf.fr> References: <20090205184209.60e09536.fabien.coutant@neuf.fr> Message-ID: <498B5126.1010606@egenix.com> On 2009-02-05 18:42, Fabien COUTANT wrote: > Le Wed, 04 Feb 2009 20:19:52 +0100, wtr_web a ?crit: >> Hello! >> I need to access a SQLServer 2005 by creating, reading and writing by >> a single thread/single user. >> Has anybody experience with some openSrc SW? There are quite large >> amounts of data involved (around a million >> rows in some tables). >> I have only used Oracle-access myself. > > Hello, > > AFAIK SQLServer speaks the same "TDS" protocol as Sybase (which it > originated from long ago). > > So you could try FreeTDS which is a C-level lib to speak this protocol: > http://www.freetds.org/ > and especially > http://www.freetds.org/userguide/python.htm > with a corresponding Python binding of this library: > http://python-sybase.sourceforge.net/ > (replaces the old > http://object-craft.com.au/projects/sybase/index.html ) > (maybe there are other bindings, didn't look further) > > FreeTDS is explicitly reporting to work with MS SQL Server, including > recent versions. And it seems much more mature and stable than pymssql... FreeTDS does work with MS SQL Server, but it has problems with Unicode and is not (yet) reliable enough to use in production. mxODBC works with FreeTDS on Linux and most other Unix platforms, but due to the above issues we have chosen to develop a new product called "mxODBC Connect" which allows you to use the client driver on the server side, rather than on the client side. For MS SQL Server you can then rely on use the very stable and performant SQL Server Native Client to interface directly to the SQL Server kernel via shared memory. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Feb 05 2009) >>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ ________________________________________________________________________ ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ From vernondcole at gmail.com Fri Feb 6 05:03:56 2009 From: vernondcole at gmail.com (Vernon Cole) Date: Thu, 5 Feb 2009 21:03:56 -0700 Subject: [DB-SIG] dbapi20.py updated for Python 3.0 Message-ID: I have just checked in adodbapi Python 3.0 compatible version to the pywin32 CVS tree. It will be released with pywin32 213 in the near future. I have made updates to the api standards compliance test to allow for the differences between Python 2.x and Python 3.0 as discussed in this forum recently. I am including my updated test as an attachment here. It can also be found in the sources of pywin32 and will be uploaded to adodbapi.sourceforge.net shortly. If any reviewer can see a problem with this test code, please let me know. This is the Python 2.x version. To obtain a Python 3.0 version, execute "2to3 -w dbapi20.py" -- Vernon Cole -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- #!/usr/bin/env python ''' Python DB API 2.0 driver compliance unit test suite. This software is Public Domain and may be used without restrictions. "Now we have booze and barflies entering the discussion, plus rumours of DBAs on drugs... and I won't tell you what flashes through my mind each time I read the subject line with 'Anal Compliance' in it. All around this is turning out to be a thoroughly unwholesome unit test." -- Ian Bicking ''' __version__ = '$Revision: 1.4 $'[11:-2] __author__ = 'Stuart Bishop ' import unittest import time import sys # Revision 3.0 2009/2/4 kf7xm # Updates to make Python 3.0 compatible # # $Log: dbapi20.py,v $ # Revision 1.4 2009/02/06 03:35:11 kf7xm # Tested okay with Python 3.0, includes last minute patches from Mark H. # # Revision 1.1.1.1.2.1 2008/09/20 19:54:59 rupole # Include latest changes from main branch # Updates for py3k # # Revision 1.1.1.1 2008/01/04 18:49:10 kf7xm # Import of the adodbapi package into pywin32. # Documentation is in readme.txt and the tests directory. # # Revision 1.10 2003/10/09 03:14:14 zenzen # Add test for DB API 2.0 optional extension, where database exceptions # are exposed as attributes on the Connection object. # # Revision 1.9 2003/08/13 01:16:36 zenzen # Minor tweak from Stefan Fleiter # # Revision 1.8 2003/04/10 00:13:25 zenzen # Changes, as per suggestions by M.-A. Lemburg # - Add a table prefix, to ensure namespace collisions can always be avoided # # Revision 1.7 2003/02/26 23:33:37 zenzen # Break out DDL into helper functions, as per request by David Rushby # # Revision 1.6 2003/02/21 03:04:33 zenzen # Stuff from Henrik Ekelund: # added test_None # added test_nextset & hooks # # Revision 1.5 2003/02/17 22:08:43 zenzen # Implement suggestions and code from Henrik Eklund - test that cursor.arraysize # defaults to 1 & generic cursor.callproc test added # # Revision 1.4 2003/02/15 00:16:33 zenzen # Changes, as per suggestions and bug reports by M.-A. Lemburg, # Matthew T. Kromer, Federico Di Gregorio and Daniel Dittmar # - Class renamed # - Now a subclass of TestCase, to avoid requiring the driver stub # to use multiple inheritance # - Reversed the polarity of buggy test in test_description # - Test exception heirarchy correctly # - self.populate is now self._populate(), so if a driver stub # overrides self.ddl1 this change propogates # - VARCHAR columns now have a width, which will hopefully make the # DDL even more portible (this will be reversed if it causes more problems) # - cursor.rowcount being checked after various execute and fetchXXX methods # - Check for fetchall and fetchmany returning empty lists after results # are exhausted (already checking for empty lists if select retrieved # nothing # - Fix bugs in test_setoutputsize_basic and test_setinputsizes # def str2bytes(sval): if sys.version_info < (3,0) and isinstance(sval, str): sval = sval.decode("latin1") return sval.encode("latin1") class DatabaseAPI20Test(unittest.TestCase): ''' Test a database self.driver for DB API 2.0 compatibility. This implementation tests Gadfly, but the TestCase is structured so that other self.drivers can subclass this test case to ensure compiliance with the DB-API. It is expected that this TestCase may be expanded in the future if ambiguities or edge conditions are discovered. The 'Optional Extensions' are not yet being tested. self.drivers should subclass this test, overriding setUp, tearDown, self.driver, connect_args and connect_kw_args. Class specification should be as follows: import dbapi20 class mytest(dbapi20.DatabaseAPI20Test): [...] Don't 'import DatabaseAPI20Test from dbapi20', or you will confuse the unit tester - just 'import dbapi20'. ''' # The self.driver module. This should be the module where the 'connect' # method is to be found driver = None connect_args = () # List of arguments to pass to connect connect_kw_args = {} # Keyword arguments for connect table_prefix = 'dbapi20test_' # If you need to specify a prefix for tables ddl1 = 'create table %sbooze (name varchar(20))' % table_prefix ddl2 = 'create table %sbarflys (name varchar(20))' % table_prefix xddl1 = 'drop table %sbooze' % table_prefix xddl2 = 'drop table %sbarflys' % table_prefix lowerfunc = 'lower' # Name of stored procedure to convert string->lowercase # Some drivers may need to override these helpers, for example adding # a 'commit' after the execute. def executeDDL1(self,cursor): cursor.execute(self.ddl1) def executeDDL2(self,cursor): cursor.execute(self.ddl2) def setUp(self): ''' self.drivers should override this method to perform required setup if any is necessary, such as creating the database. ''' pass def tearDown(self): ''' self.drivers should override this method to perform required cleanup if any is necessary, such as deleting the test database. The default drops the tables that may be created. ''' con = self._connect() try: cur = con.cursor() for ddl in (self.xddl1,self.xddl2): try: cur.execute(ddl) con.commit() except self.driver.Error: # Assume table didn't exist. Other tests will check if # execute is busted. pass finally: con.close() def _connect(self): try: return self.driver.connect( *self.connect_args,**self.connect_kw_args ) except AttributeError: self.fail("No connect method found in self.driver module") def test_connect(self): con = self._connect() con.close() def test_apilevel(self): try: # Must exist apilevel = self.driver.apilevel # Must equal 2.0 self.assertEqual(apilevel,'2.0') except AttributeError: self.fail("Driver doesn't define apilevel") def test_threadsafety(self): try: # Must exist threadsafety = self.driver.threadsafety # Must be a valid value self.failUnless(threadsafety in (0,1,2,3)) except AttributeError: self.fail("Driver doesn't define threadsafety") def test_paramstyle(self): try: # Must exist paramstyle = self.driver.paramstyle # Must be a valid value self.failUnless(paramstyle in ( 'qmark','numeric','named','format','pyformat' )) except AttributeError: self.fail("Driver doesn't define paramstyle") def test_Exceptions(self): # Make sure required exceptions exist, and are in the # defined heirarchy. if sys.version[0] == '3': #under Python 3 StardardError no longer exists self.failUnless(issubclass(self.driver.Warning,Exception)) self.failUnless(issubclass(self.driver.Error,Exception)) else: self.failUnless(issubclass(self.driver.Warning,StandardError)) self.failUnless(issubclass(self.driver.Error,StandardError)) self.failUnless( issubclass(self.driver.InterfaceError,self.driver.Error)) self.failUnless( issubclass(self.driver.DatabaseError,self.driver.Error) ) self.failUnless( issubclass(self.driver.OperationalError,self.driver.Error) ) self.failUnless( issubclass(self.driver.IntegrityError,self.driver.Error) ) self.failUnless( issubclass(self.driver.InternalError,self.driver.Error) ) self.failUnless( issubclass(self.driver.ProgrammingError,self.driver.Error) ) self.failUnless( issubclass(self.driver.NotSupportedError,self.driver.Error) ) def test_ExceptionsAsConnectionAttributes(self): # OPTIONAL EXTENSION # Test for the optional DB API 2.0 extension, where the exceptions # are exposed as attributes on the Connection object # I figure this optional extension will be implemented by any # driver author who is using this test suite, so it is enabled # by default. con = self._connect() drv = self.driver self.failUnless(con.Warning is drv.Warning) self.failUnless(con.Error is drv.Error) self.failUnless(con.InterfaceError is drv.InterfaceError) self.failUnless(con.DatabaseError is drv.DatabaseError) self.failUnless(con.OperationalError is drv.OperationalError) self.failUnless(con.IntegrityError is drv.IntegrityError) self.failUnless(con.InternalError is drv.InternalError) self.failUnless(con.ProgrammingError is drv.ProgrammingError) self.failUnless(con.NotSupportedError is drv.NotSupportedError) def test_commit(self): con = self._connect() try: # Commit must work, even if it doesn't do anything con.commit() finally: con.close() def test_rollback(self): con = self._connect() # If rollback is defined, it should either work or throw # the documented exception if hasattr(con,'rollback'): try: con.rollback() except self.driver.NotSupportedError: pass def test_cursor(self): con = self._connect() try: cur = con.cursor() finally: con.close() def test_cursor_isolation(self): con = self._connect() try: # Make sure cursors created from the same connection have # the documented transaction isolation level cur1 = con.cursor() cur2 = con.cursor() self.executeDDL1(cur1) cur1.execute("insert into %sbooze values ('Victoria Bitter')" % ( self.table_prefix )) cur2.execute("select name from %sbooze" % self.table_prefix) booze = cur2.fetchall() self.assertEqual(len(booze),1) self.assertEqual(len(booze[0]),1) self.assertEqual(booze[0][0],'Victoria Bitter') finally: con.close() def test_description(self): con = self._connect() try: cur = con.cursor() self.executeDDL1(cur) self.assertEqual(cur.description,None, 'cursor.description should be none after executing a ' 'statement that can return no rows (such as DDL)' ) cur.execute('select name from %sbooze' % self.table_prefix) self.assertEqual(len(cur.description),1, 'cursor.description describes too many columns' ) self.assertEqual(len(cur.description[0]),7, 'cursor.description[x] tuples must have 7 elements' ) self.assertEqual(cur.description[0][0].lower(),'name', 'cursor.description[x][0] must return column name' ) self.assertEqual(cur.description[0][1],self.driver.STRING, 'cursor.description[x][1] must return column type. Got %r' % cur.description[0][1] ) # Make sure self.description gets reset self.executeDDL2(cur) self.assertEqual(cur.description,None, 'cursor.description not being set to None when executing ' 'no-result statements (eg. DDL)' ) finally: con.close() def test_rowcount(self): con = self._connect() try: cur = con.cursor() self.executeDDL1(cur) self.assertEqual(cur.rowcount,-1, 'cursor.rowcount should be -1 after executing no-result ' 'statements' ) cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( self.table_prefix )) self.failUnless(cur.rowcount in (-1,1), 'cursor.rowcount should == number or rows inserted, or ' 'set to -1 after executing an insert statement' ) cur.execute("select name from %sbooze" % self.table_prefix) self.failUnless(cur.rowcount in (-1,1), 'cursor.rowcount should == number of rows returned, or ' 'set to -1 after executing a select statement' ) self.executeDDL2(cur) self.assertEqual(cur.rowcount,-1, 'cursor.rowcount not being reset to -1 after executing ' 'no-result statements' ) finally: con.close() lower_func = 'lower' def test_callproc(self): con = self._connect() try: cur = con.cursor() if self.lower_func and hasattr(cur,'callproc'): r = cur.callproc(self.lower_func,('FOO',)) self.assertEqual(len(r),1) self.assertEqual(r[0],'FOO') r = cur.fetchall() self.assertEqual(len(r),1,'callproc produced no result set') self.assertEqual(len(r[0]),1, 'callproc produced invalid result set' ) self.assertEqual(r[0][0],'foo', 'callproc produced invalid results' ) finally: con.close() def test_close(self): con = self._connect() try: cur = con.cursor() finally: con.close() # cursor.execute should raise an Error if called after connection # closed self.assertRaises(self.driver.Error,self.executeDDL1,cur) # connection.commit should raise an Error if called after connection' # closed.' self.assertRaises(self.driver.Error,con.commit) # connection.close should raise an Error if called more than once self.assertRaises(self.driver.Error,con.close) def test_execute(self): con = self._connect() try: cur = con.cursor() self._paraminsert(cur) finally: con.close() def _paraminsert(self,cur): self.executeDDL1(cur) cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( self.table_prefix )) self.failUnless(cur.rowcount in (-1,1)) if self.driver.paramstyle == 'qmark': cur.execute( 'insert into %sbooze values (?)' % self.table_prefix, ("Cooper's",) ) elif self.driver.paramstyle == 'numeric': cur.execute( 'insert into %sbooze values (:1)' % self.table_prefix, ("Cooper's",) ) elif self.driver.paramstyle == 'named': cur.execute( 'insert into %sbooze values (:beer)' % self.table_prefix, {'beer':"Cooper's"} ) elif self.driver.paramstyle == 'format': cur.execute( 'insert into %sbooze values (%%s)' % self.table_prefix, ("Cooper's",) ) elif self.driver.paramstyle == 'pyformat': cur.execute( 'insert into %sbooze values (%%(beer)s)' % self.table_prefix, {'beer':"Cooper's"} ) else: self.fail('Invalid paramstyle') self.failUnless(cur.rowcount in (-1,1)) cur.execute('select name from %sbooze' % self.table_prefix) res = cur.fetchall() self.assertEqual(len(res),2,'cursor.fetchall returned too few rows') beers = [res[0][0],res[1][0]] beers.sort() self.assertEqual(beers[0],"Cooper's", 'cursor.fetchall retrieved incorrect data, or data inserted ' 'incorrectly' ) self.assertEqual(beers[1],"Victoria Bitter", 'cursor.fetchall retrieved incorrect data, or data inserted ' 'incorrectly' ) def test_executemany(self): con = self._connect() try: cur = con.cursor() self.executeDDL1(cur) largs = [ ("Cooper's",) , ("Boag's",) ] margs = [ {'beer': "Cooper's"}, {'beer': "Boag's"} ] if self.driver.paramstyle == 'qmark': cur.executemany( 'insert into %sbooze values (?)' % self.table_prefix, largs ) elif self.driver.paramstyle == 'numeric': cur.executemany( 'insert into %sbooze values (:1)' % self.table_prefix, largs ) elif self.driver.paramstyle == 'named': cur.executemany( 'insert into %sbooze values (:beer)' % self.table_prefix, margs ) elif self.driver.paramstyle == 'format': cur.executemany( 'insert into %sbooze values (%%s)' % self.table_prefix, largs ) elif self.driver.paramstyle == 'pyformat': cur.executemany( 'insert into %sbooze values (%%(beer)s)' % ( self.table_prefix ), margs ) else: self.fail('Unknown paramstyle') self.failUnless(cur.rowcount in (-1,2), 'insert using cursor.executemany set cursor.rowcount to ' 'incorrect value %r' % cur.rowcount ) cur.execute('select name from %sbooze' % self.table_prefix) res = cur.fetchall() self.assertEqual(len(res),2, 'cursor.fetchall retrieved incorrect number of rows' ) beers = [res[0][0],res[1][0]] beers.sort() self.assertEqual(beers[0],"Boag's",'incorrect data retrieved') self.assertEqual(beers[1],"Cooper's",'incorrect data retrieved') finally: con.close() def test_fetchone(self): con = self._connect() try: cur = con.cursor() # cursor.fetchone should raise an Error if called before # executing a select-type query self.assertRaises(self.driver.Error,cur.fetchone) # cursor.fetchone should raise an Error if called after # executing a query that cannnot return rows self.executeDDL1(cur) self.assertRaises(self.driver.Error,cur.fetchone) cur.execute('select name from %sbooze' % self.table_prefix) self.assertEqual(cur.fetchone(),None, 'cursor.fetchone should return None if a query retrieves ' 'no rows' ) self.failUnless(cur.rowcount in (-1,0)) # cursor.fetchone should raise an Error if called after # executing a query that cannnot return rows cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( self.table_prefix )) self.assertRaises(self.driver.Error,cur.fetchone) cur.execute('select name from %sbooze' % self.table_prefix) r = cur.fetchone() self.assertEqual(len(r),1, 'cursor.fetchone should have retrieved a single row' ) self.assertEqual(r[0],'Victoria Bitter', 'cursor.fetchone retrieved incorrect data' ) self.assertEqual(cur.fetchone(),None, 'cursor.fetchone should return None if no more rows available' ) self.failUnless(cur.rowcount in (-1,1)) finally: con.close() samples = [ 'Carlton Cold', 'Carlton Draft', 'Mountain Goat', 'Redback', 'Victoria Bitter', 'XXXX' ] def _populate(self): ''' Return a list of sql commands to setup the DB for the fetch tests. ''' populate = [ "insert into %sbooze values ('%s')" % (self.table_prefix,s) for s in self.samples ] return populate def test_fetchmany(self): con = self._connect() try: cur = con.cursor() # cursor.fetchmany should raise an Error if called without #issuing a query self.assertRaises(self.driver.Error,cur.fetchmany,4) self.executeDDL1(cur) for sql in self._populate(): cur.execute(sql) cur.execute('select name from %sbooze' % self.table_prefix) r = cur.fetchmany() self.assertEqual(len(r),1, 'cursor.fetchmany retrieved incorrect number of rows, ' 'default of arraysize is one.' ) cur.arraysize=10 r = cur.fetchmany(3) # Should get 3 rows self.assertEqual(len(r),3, 'cursor.fetchmany retrieved incorrect number of rows' ) r = cur.fetchmany(4) # Should get 2 more self.assertEqual(len(r),2, 'cursor.fetchmany retrieved incorrect number of rows' ) r = cur.fetchmany(4) # Should be an empty sequence self.assertEqual(len(r),0, 'cursor.fetchmany should return an empty sequence after ' 'results are exhausted' ) self.failUnless(cur.rowcount in (-1,6)) # Same as above, using cursor.arraysize cur.arraysize=4 cur.execute('select name from %sbooze' % self.table_prefix) r = cur.fetchmany() # Should get 4 rows self.assertEqual(len(r),4, 'cursor.arraysize not being honoured by fetchmany' ) r = cur.fetchmany() # Should get 2 more self.assertEqual(len(r),2) r = cur.fetchmany() # Should be an empty sequence self.assertEqual(len(r),0) self.failUnless(cur.rowcount in (-1,6)) cur.arraysize=6 cur.execute('select name from %sbooze' % self.table_prefix) rows = cur.fetchmany() # Should get all rows self.failUnless(cur.rowcount in (-1,6)) self.assertEqual(len(rows),6) self.assertEqual(len(rows),6) rows = [r[0] for r in rows] rows.sort() # Make sure we get the right data back out for i in range(0,6): self.assertEqual(rows[i],self.samples[i], 'incorrect data retrieved by cursor.fetchmany' ) rows = cur.fetchmany() # Should return an empty list self.assertEqual(len(rows),0, 'cursor.fetchmany should return an empty sequence if ' 'called after the whole result set has been fetched' ) self.failUnless(cur.rowcount in (-1,6)) self.executeDDL2(cur) cur.execute('select name from %sbarflys' % self.table_prefix) r = cur.fetchmany() # Should get empty sequence self.assertEqual(len(r),0, 'cursor.fetchmany should return an empty sequence if ' 'query retrieved no rows' ) self.failUnless(cur.rowcount in (-1,0)) finally: con.close() def test_fetchall(self): con = self._connect() try: cur = con.cursor() # cursor.fetchall should raise an Error if called # without executing a query that may return rows (such # as a select) self.assertRaises(self.driver.Error, cur.fetchall) self.executeDDL1(cur) for sql in self._populate(): cur.execute(sql) # cursor.fetchall should raise an Error if called # after executing a a statement that cannot return rows self.assertRaises(self.driver.Error,cur.fetchall) cur.execute('select name from %sbooze' % self.table_prefix) rows = cur.fetchall() self.failUnless(cur.rowcount in (-1,len(self.samples))) self.assertEqual(len(rows),len(self.samples), 'cursor.fetchall did not retrieve all rows' ) rows = [r[0] for r in rows] rows.sort() for i in range(0,len(self.samples)): self.assertEqual(rows[i],self.samples[i], 'cursor.fetchall retrieved incorrect rows' ) rows = cur.fetchall() self.assertEqual( len(rows),0, 'cursor.fetchall should return an empty list if called ' 'after the whole result set has been fetched' ) self.failUnless(cur.rowcount in (-1,len(self.samples))) self.executeDDL2(cur) cur.execute('select name from %sbarflys' % self.table_prefix) rows = cur.fetchall() self.failUnless(cur.rowcount in (-1,0)) self.assertEqual(len(rows),0, 'cursor.fetchall should return an empty list if ' 'a select query returns no rows' ) finally: con.close() def test_mixedfetch(self): con = self._connect() try: cur = con.cursor() self.executeDDL1(cur) for sql in self._populate(): cur.execute(sql) cur.execute('select name from %sbooze' % self.table_prefix) rows1 = cur.fetchone() rows23 = cur.fetchmany(2) rows4 = cur.fetchone() rows56 = cur.fetchall() self.failUnless(cur.rowcount in (-1,6)) self.assertEqual(len(rows23),2, 'fetchmany returned incorrect number of rows' ) self.assertEqual(len(rows56),2, 'fetchall returned incorrect number of rows' ) rows = [rows1[0]] rows.extend([rows23[0][0],rows23[1][0]]) rows.append(rows4[0]) rows.extend([rows56[0][0],rows56[1][0]]) rows.sort() for i in range(0,len(self.samples)): self.assertEqual(rows[i],self.samples[i], 'incorrect data retrieved or inserted' ) finally: con.close() def help_nextset_setUp(self,cur): ''' Should create a procedure called deleteme that returns two result sets, first the number of rows in booze then "name from booze" ''' raise NotImplementedError('Helper not implemented') #sql=""" # create procedure deleteme as # begin # select count(*) from booze # select name from booze # end #""" #cur.execute(sql) def help_nextset_tearDown(self,cur): 'If cleaning up is needed after nextSetTest' raise NotImplementedError('Helper not implemented') #cur.execute("drop procedure deleteme") def test_nextset(self): con = self._connect() try: cur = con.cursor() if not hasattr(cur,'nextset'): return try: self.executeDDL1(cur) sql=self._populate() for sql in self._populate(): cur.execute(sql) self.help_nextset_setUp(cur) cur.callproc('deleteme') numberofrows=cur.fetchone() assert numberofrows[0]== len(self.samples) assert cur.nextset() names=cur.fetchall() assert len(names) == len(self.samples) s=cur.nextset() assert s == None,'No more return sets, should return None' finally: self.help_nextset_tearDown(cur) finally: con.close() def test_nextset(self): raise NotImplementedError('Drivers need to override this test') def test_arraysize(self): # Not much here - rest of the tests for this are in test_fetchmany con = self._connect() try: cur = con.cursor() self.failUnless(hasattr(cur,'arraysize'), 'cursor.arraysize must be defined' ) finally: con.close() def test_setinputsizes(self): con = self._connect() try: cur = con.cursor() cur.setinputsizes( (25,) ) self._paraminsert(cur) # Make sure cursor still works finally: con.close() def test_setoutputsize_basic(self): # Basic test is to make sure setoutputsize doesn't blow up con = self._connect() try: cur = con.cursor() cur.setoutputsize(1000) cur.setoutputsize(2000,0) self._paraminsert(cur) # Make sure the cursor still works finally: con.close() def test_setoutputsize(self): # Real test for setoutputsize is driver dependant raise NotImplementedError('Driver needed to override this test') def test_None(self): con = self._connect() try: cur = con.cursor() self.executeDDL1(cur) cur.execute('insert into %sbooze values (NULL)' % self.table_prefix) cur.execute('select name from %sbooze' % self.table_prefix) r = cur.fetchall() self.assertEqual(len(r),1) self.assertEqual(len(r[0]),1) self.assertEqual(r[0][0],None,'NULL value not returned as None') finally: con.close() def test_Date(self): d1 = self.driver.Date(2002,12,25) d2 = self.driver.DateFromTicks(time.mktime((2002,12,25,0,0,0,0,0,0))) # Can we assume this? API doesn't specify, but it seems implied # self.assertEqual(str(d1),str(d2)) def test_Time(self): t1 = self.driver.Time(13,45,30) t2 = self.driver.TimeFromTicks(time.mktime((2001,1,1,13,45,30,0,0,0))) # Can we assume this? API doesn't specify, but it seems implied # self.assertEqual(str(t1),str(t2)) def test_Timestamp(self): t1 = self.driver.Timestamp(2002,12,25,13,45,30) t2 = self.driver.TimestampFromTicks( time.mktime((2002,12,25,13,45,30,0,0,0)) ) # Can we assume this? API doesn't specify, but it seems implied # self.assertEqual(str(t1),str(t2)) def test_Binary(self): b = self.driver.Binary(str2bytes('Something')) b = self.driver.Binary(str2bytes('')) def test_STRING(self): self.failUnless(hasattr(self.driver,'STRING'), 'module.STRING must be defined' ) def test_BINARY(self): self.failUnless(hasattr(self.driver,'BINARY'), 'module.BINARY must be defined.' ) def test_NUMBER(self): self.failUnless(hasattr(self.driver,'NUMBER'), 'module.NUMBER must be defined.' ) def test_DATETIME(self): self.failUnless(hasattr(self.driver,'DATETIME'), 'module.DATETIME must be defined.' ) def test_ROWID(self): self.failUnless(hasattr(self.driver,'ROWID'), 'module.ROWID must be defined.' ) From wilk at flibuste.net Tue Feb 10 15:46:10 2009 From: wilk at flibuste.net (William Dode) Date: Tue, 10 Feb 2009 14:46:10 +0000 (UTC) Subject: [DB-SIG] adodbapi return datetime Message-ID: Hi, How should i do to make adodbapi return datetime instead of mx.DateTime? I tried import adodbapi adodbapi.dateconverter = adodbapi.pythonDateTimeConverter() Maybe i didn't test well, but it doesn't seems to work... thanks -- William Dod? - http://flibuste.net Informaticien Ind?pendant From vernondcole at gmail.com Tue Feb 10 16:28:29 2009 From: vernondcole at gmail.com (Vernon Cole) Date: Tue, 10 Feb 2009 08:28:29 -0700 Subject: [DB-SIG] adodbapi return datetime In-Reply-To: References: Message-ID: William: It has always seemed to me that the syntax you tried should work. Perhaps someday, some "real" Python guru will explain to me why sometimes it does not, and maybe even tell me how to fix it. Perhaps the module definition is not done quite right, I dunno? Try adding an extra level of depth to your module reference, and I think you may find that it works. adodbapi.adodbapi.dateconverter = adodbapi.adodbapi.pythonDateTimeConverter() Looks weird to me and I don't understand it, but try it. -- Vernon Cole On Tue, Feb 10, 2009 at 7:46 AM, William Dode wrote: > Hi, > > How should i do to make adodbapi return datetime instead of mx.DateTime? > > I tried > import adodbapi > adodbapi.dateconverter = adodbapi.pythonDateTimeConverter() > > Maybe i didn't test well, but it doesn't seems to work... > > thanks > > -- > William Dod? - http://flibuste.net > Informaticien Ind?pendant > > _______________________________________________ > DB-SIG maillist - DB-SIG at python.org > http://mail.python.org/mailman/listinfo/db-sig > -------------- next part -------------- An HTML attachment was scrubbed... URL: From wilk at flibuste.net Tue Feb 10 16:49:47 2009 From: wilk at flibuste.net (William Dode) Date: Tue, 10 Feb 2009 15:49:47 +0000 (UTC) Subject: [DB-SIG] adodbapi return datetime References: Message-ID: On 10-02-2009, Vernon Cole wrote: > William: > It has always seemed to me that the syntax you tried should work. Perhaps > someday, some "real" Python guru will explain to me why sometimes it does > not, and maybe even tell me how to fix it. Perhaps the module definition is > not done quite right, I dunno? Try adding an extra level of depth to your > module reference, and I think you may find that it works. > adodbapi.adodbapi.dateconverter = adodbapi.adodbapi.pythonDateTimeConverter() > > Looks weird to me and I don't understand it, but try it. It works ! thanks you to answer so quickly. Do you plan to make datetime the default ? It's weird that with python >= 2.3 the behaviour will silently change if we add mx package ! -- William Dod? - http://flibuste.net Informaticien Ind?pendant From vernondcole at gmail.com Tue Feb 10 17:12:21 2009 From: vernondcole at gmail.com (Vernon Cole) Date: Tue, 10 Feb 2009 09:12:21 -0700 Subject: [DB-SIG] adodbapi return datetime In-Reply-To: References: Message-ID: This is a poll: Should adodbapi be changed so that datetime.datetime is the default return type for SQL date-time columns? (The present implementation will default to mx.DateTime if present.) My feeling is "yes", because 1) the Python 3.0 version of pywin32 will return COM date-times as datetime.datetime 2) mx.DateTime is not (yet?) available on Python 3.0 nor IronPython 3) as William said, it IS weird to silently change when mxbase is loaded. But, I am worried about breaking existing code if I change the default. Your comments solicited... -- VC On Tue, Feb 10, 2009 at 8:49 AM, William Dode wrote: > On 10-02-2009, Vernon Cole wrote: > > > William: > > It has always seemed to me that the syntax you tried should work. Perhaps > > someday, some "real" Python guru will explain to me why sometimes it does > > not, and maybe even tell me how to fix it. Perhaps the module definition > is > > not done quite right, I dunno? Try adding an extra level of depth to your > > module reference, and I think you may find that it works. > > > adodbapi.adodbapi.dateconverter = > adodbapi.adodbapi.pythonDateTimeConverter() > > > > > Looks weird to me and I don't understand it, but try it. > > It works ! thanks you to answer so quickly. > > Do you plan to make datetime the default ? > > It's weird that with python >= 2.3 the behaviour will silently change if > we add mx package ! > > -- > William Dod? - http://flibuste.net > Informaticien Ind?pendant > > _______________________________________________ > DB-SIG maillist - DB-SIG at python.org > http://mail.python.org/mailman/listinfo/db-sig > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fumanchu at aminus.org Tue Feb 10 18:20:55 2009 From: fumanchu at aminus.org (Robert Brewer) Date: Tue, 10 Feb 2009 09:20:55 -0800 Subject: [DB-SIG] adodbapi return datetime In-Reply-To: References: Message-ID: Vernon Cole wrote: > Should adodbapi be changed so that datetime.datetime is > the default return type for SQL date-time columns? Almost certainly at the next major version. That's the easy part. Now the hard part: get the community to design, build, and release the next major version. You have my most sincere wishes of luck, but it will take a lot more than that. ;) Robert Brewer fumanchu at aminus.org From wilk at flibuste.net Tue Feb 10 18:42:02 2009 From: wilk at flibuste.net (William Dode) Date: Tue, 10 Feb 2009 17:42:02 +0000 (UTC) Subject: [DB-SIG] adodbapi return datetime References: Message-ID: On 10-02-2009, Robert Brewer wrote: > Vernon Cole wrote: >> Should adodbapi be changed so that datetime.datetime is >> the default return type for SQL date-time columns? > > Almost certainly at the next major version. For me the weird problem of a different behaviour if mx is installed or not is enough to change this in a minor version. The question will be, what to do if the release stay compatible with python < 2.3 iirc Guido argued to put this (datetime by default) in the dbapi spec isn'it ? -- William Dod? - http://flibuste.net Informaticien Ind?pendant From mal at egenix.com Tue Feb 10 19:14:11 2009 From: mal at egenix.com (M.-A. Lemburg) Date: Tue, 10 Feb 2009 19:14:11 +0100 Subject: [DB-SIG] adodbapi return datetime In-Reply-To: References: Message-ID: <4991C3F3.7050105@egenix.com> On 2009-02-10 18:42, William Dode wrote: > On 10-02-2009, Robert Brewer wrote: >> Vernon Cole wrote: >>> Should adodbapi be changed so that datetime.datetime is >>> the default return type for SQL date-time columns? >> Almost certainly at the next major version. It's probably better to make this an explicit choice. > For me the weird problem of a different behaviour if mx is installed or > not is enough to change this in a minor version. > > The question will be, what to do if the release stay compatible with > python < 2.3 > > iirc Guido argued to put this (datetime by default) in the dbapi spec > isn'it ? The DB-API allows the module to make a choice of which implementation to use. mxDateTime has been the defacto standard for many years, so there's a lot of code out there relying on it and mxDateTime is still very much alive. Database modules are free to support more than just one way to interface to date/time values in databases, e.g. Unix ticks, time tuples, strings, mxDateTime, datetime module, custom types, etc. The spec itself doesn't mandate a default. You have the same situation for monetary values, decimal values, blobs and text. -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Feb 10 2009) >>> Python/Zope Consulting and Support ... http://www.egenix.com/ >>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ >>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/ ________________________________________________________________________ ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ From jd at commandprompt.com Tue Feb 10 19:27:41 2009 From: jd at commandprompt.com (Joshua D. Drake) Date: Tue, 10 Feb 2009 10:27:41 -0800 Subject: [DB-SIG] PostgreSQL Conference East looking for speakers. Message-ID: <1234290461.6388.52.camel@jd-laptop.pragmaticzealot.org> PostgreSQL Conference East is being held at historic Drexel University on April 3rd through 5th 2009 . This is a community conference and the proceeds benefit United States PostgreSQL. This is the second call for papers. The call for papers ends Feb 23rd and speakers will be notified on the 27th. You may submit your talk here: http://www.postgresqlconference.org . We are looking for a wide range of topics. Can you speak on any of the below topics? What about a different topic? As long as it is centered around PostgreSQL we want to hear about it. The generic call is below but it would be fantastic if we could get some python folks to talk about working PostgreSQL from Python or particular challenges that are faced by supported PostgreSQL with Python. Hacker topics: MVCC C Function development Writing Procedural Languages Creating types The planner Optimization tips Explaining the process model DBA topics: Backing up PostgreSQL Understanding and Configuring Autovacuum Normalization Trigger Happy (how to use triggers ;) PITR -- happiness is a shipped transaction log User / Groups / Roles Security End User development: Web Frameworks with PostgreSQL Pylons Grails Rails Cake Turbo Gears Django Solutions: Do you have a successful case study to present? How did you solve a problem with PostgreSQL? Do you have an Open Source product that runs on PostgreSQL? As always we let the presenters drive the feel of the conference. If you have an itch, let's figure out how to scratch it (as long as it is with PostgreSQL). Submit your paper today: http://www.postgresqlconference.org/ -- PostgreSQL - XMPP: jdrake at jabber.postgresql.org Consulting, Development, Support, Training 503-667-4564 - http://www.commandprompt.com/ The PostgreSQL Company, serving since 1997 From wilk at flibuste.net Tue Feb 10 21:01:11 2009 From: wilk at flibuste.net (William Dode) Date: Tue, 10 Feb 2009 20:01:11 +0000 (UTC) Subject: [DB-SIG] adodbapi return datetime References: <4991C3F3.7050105@egenix.com> Message-ID: On 10-02-2009, M.-A. Lemburg wrote: > On 2009-02-10 18:42, William Dode wrote: >> On 10-02-2009, Robert Brewer wrote: >>> Vernon Cole wrote: >>>> Should adodbapi be changed so that datetime.datetime is >>>> the default return type for SQL date-time columns? >>> Almost certainly at the next major version. > > It's probably better to make this an explicit choice. > >> For me the weird problem of a different behaviour if mx is installed or >> not is enough to change this in a minor version. >> >> The question will be, what to do if the release stay compatible with >> python < 2.3 >> >> iirc Guido argued to put this (datetime by default) in the dbapi spec >> isn'it ? > > The DB-API allows the module to make a choice of which implementation > to use. mxDateTime has been the defacto standard for many years, so > there's a lot of code out there relying on it and mxDateTime is > still very much alive. > > Database modules are free to support more than just one way to interface > to date/time values in databases, e.g. Unix ticks, time tuples, > strings, mxDateTime, datetime module, custom types, etc. The spec > itself doesn't mandate a default. It could be one by default and in the same time let the user choose an other one. Anyway i don't care a lot, we can let the defacto standard change slowly at the rythm of each database... Could we make a round table now ? -- William Dod? - http://flibuste.net Informaticien Ind?pendant From wtr_web at wtresearch.de Tue Feb 10 19:42:30 2009 From: wtr_web at wtresearch.de (wtr_web) Date: Tue, 10 Feb 2009 19:42:30 +0100 Subject: [DB-SIG] py<--->sqlserver In-Reply-To: References: Message-ID: <9D764AAB-86D3-4CF6-887C-B00C39821DF2@wtresearch.de> Hello! I want to thank all of you who have sent me lots of valuable information! I felt even a bit overwhelmed... I have to check/test, what is best suited for this one-time task of moving/combining data from several databases into a new joint structure. The "real" programming will be done with C# (by another person). Thanks, again, I wish i could be of help myself in the future wolfgang From anthony.tuininga at gmail.com Tue Feb 17 06:15:28 2009 From: anthony.tuininga at gmail.com (Anthony Tuininga) Date: Mon, 16 Feb 2009 22:15:28 -0700 Subject: [DB-SIG] cx_Oracle 5.0.1 Message-ID: <703ae56b0902162115y73f76ea6te00dd04af5a519e2@mail.gmail.com> What is cx_Oracle? cx_Oracle is a Python extension module that allows access to Oracle and conforms to the Python database API 2.0 specifications with a few exceptions. Where do I get it? http://cx-oracle.sourceforge.net What's new? 1) Added support for database change notification available in Oracle 10g Release 2 and higher. 2) Fixed bug where NCLOB data would be corrupted upon retrieval (non Unicode mode) or would generate exception ORA-24806 (LOB form mismatch). Oracle insists upon differentiating between CLOB and NCLOB no matter which character set is being used for retrieval. 3) Added new attributes size, bufferSize and numElements to variable objects, deprecating allocelems (replaced by numElements) and maxlength (replaced by bufferSize) 4) Avoided increasing memory allocation for strings when using variable width character sets and increasing the number of elements in a variable during executemany(). 5) Tweaked code in order to ensure that cx_Oracle can compile with Python 3.0.1.