5

In my server code, there is a call to _SO_fetchAlternateID (nested in some value call), which ultimately calls makeConnection in pgconnection.py.

This call fails on conn.autocommit(1), with the error

TypeError: 'bool' object is not callable

Here is SQLObject's (0.8.7) code:

def makeConnection(self):
try:
    if self.use_dsn:
        conn = self.module.connect(self.dsn)
    else:
        conn = self.module.connect(**self.dsn_dict)
except self.module.OperationalError, e:
    raise self.module.OperationalError("%s; used connection string %r" % (e, self.dsn))
if self.autoCommit:
    # psycopg2 does not have an autocommit method.
    if hasattr(conn, 'autocommit'):
        conn.autocommit(1)
return conn

Debugging shows that conn indeed holds a connection object, but autocommit is not a method but instead a boolean (False).

self.module is module 'psycopg2' (2.4.2).

Is this a configuration issue? mismatching versions?

UPDATE:

The cause turns out to be an incompatibility issue in psycopg2-2.4.2. Looking at the C source code, psycopg/connection.h has an integer variable unfortunately named autocommit. Version 2-2.4 works ok.

Ovesh
  • 5,209
  • 11
  • 53
  • 73

2 Answers2

5

You have just spotted a bug. Take a look at this code:

def _setAutoCommit(self, conn, auto):
    # psycopg2 does not have an autocommit method.
    if hasattr(conn, 'autocommit'):
        conn.autocommit(auto)

It assumes that conn (type: psycopg2.connection) may not have an autocommit property, but when it has one, it has to be a function. It is wrong in context of psycopg2.connection, where psycopg2.connection.autocommit is a bool.

The same assumption is taken in makeConnection as you mentioned, and few other functions in there.

This could be fixed by changing every call like conn.autocommit(val) to conn.autocommit = val, which should be easy, even with sed.

Dr McKay
  • 2,548
  • 2
  • 21
  • 26
  • I saw that code. But I also debugged the same code other computers running the same versions of SQLObject and psycopg2 where `hasattr(conn, 'autocommit')` is False. – Ovesh Jun 21 '11 at 07:33
  • @Ovesh That's weird. `autocommit` (just like whole `connection`) comes from C source of this module and in this source it is declared as `int` (for Python, it is `bool`, as C doesn't have any explicitly boolean type) in `psycopg/connection.h`. There's no way it wouldn't exists or be a function (if you were really using the same code - maybe some import failed or `conn` was `None`?). – Dr McKay Jun 21 '11 at 20:28
  • I'm pretty sure it behaved the way I said it does on other machines. They are, however, running slightly different versions: 2-2.4 instead of 2-2.4.2. There's no way for me to look at the C source on their machines, because it's already compiled into an so file. – Ovesh Jun 22 '11 at 06:08
  • OK, just had a look at 2-2.4 source code, and it turns out that `psycopg/connection.h` doesn't have the autocommit member. So that was the reason. Thanks for leading the way, I'll accept your answer and edit my question to reflect the cause. – Ovesh Jun 22 '11 at 06:12
1

It sound like that somewhere in the code somebody assign autocommit = True to the conn object.

When the interpreter reach the :

 conn.autocommit(1) 

In fact it evaluates:

 True(1) 

Check the content of self.dsn or self.dsn_dict, if there is not a 'autocommit' boolean key.

VGE
  • 4,171
  • 18
  • 17
  • I looked through the SQLObject files. "dsn" and "dsn_dict" appear only in postgres/pgconnection.py (which makes sense), but autocommit was not set anywhere. I'm pretty convinced this is an incompatibility issue between the SQLObject and psycopg2 versions. – Ovesh Jun 20 '11 at 07:52