Python bindings: Account.getName() raises TypeError

John Ralls jralls at
Tue Mar 18 10:28:56 EDT 2014

On Mar 18, 2014, at 6:30 AM, Derek Atkins <warlord at MIT.EDU> wrote:

> John Ralls <jralls at> writes:
>> On Mar 17, 2014, at 10:52 AM, Derek Atkins <warlord at> wrote:
>>> John Ralls <jralls at> writes:
>>>>> TypeError: in method 'xaccAccountGetName', argument 1 of type
>>>>> Account const *'
>>> [snip]
>>>> The signature of xaccAccountGetName is const char* xaccAccountGetName
>>>> (const Account *); the const was added in 2005. A "const Account *" is
>>>> not the same as an "Account const *": The former means that the
>>>> contents of the pointer won't change, the latter means that the
>>>> pointer itself won't change (see
>>>> Somewhere in the SWIG-generated Python-to-C translation code the
>>>> argument type is wrong, but it's not directly in the stack trace from
>>>> Python. It's more likely due to a change in SWIG than to a change in
>>>> GnuCash.
>>> Could it be a const v non-const issue?  I.e., if python has an Account*
>>> object (non-const) does it realize that it can pass it to a function
>>> that is asking for a const object (either const Account* or Account
>>> const * -- doesn't matter)?  C certainly knows this, but it sounds like
>>> Python might not.
>> At that level, it’s all C; in this case it’s C generated by SWIG
>> instead of written by hand, but it’s still C.
>> Python doesn’t even have the concept of const, and its handling of
>> types is deliberately generic: If an object has a member with the
>> right name, it’s happy.
> Is the TypeError coming from Python or coming from the SWIG bindings?
> The fact that Python doesn't know about 'const' is exactly my point.  It
> probably sees "Account *" and "Account const *" as two distinct types,
> which would explain why it's complaining about the "Type Error".

My point is that Python barely knows about type at all, except for its own built-in types [1]. It will raise a TypeError if you try to divide a string, like this:
>>> 'foo' / 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'int'
or dereference an index of something that isn't a sequence and so on. Otherwise it blithely tries to do what you ask it, raising an AttributeError if you try to dereference a non-existant class member, which includes calling a function that the object's class doesn't have:
>>> 'foo'.framish()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'framish'

Python doesn't have a way to declare type arguments to a function, so it can't raise a TypeError if an argument is the wrong type: It has no way of knowing. One can write code like this:
  if not isinstance(foo, 'Account'):
     raise TypeError("foo is a %s which is not a subclass of Account" % type(foo))

But it's rare to see that in live code. It's considered more "Pythonic" to try to do what you want and handle the exception if it fails.

John Ralls


More information about the gnucash-devel mailing list