pyclibrary icon indicating copy to clipboard operation
pyclibrary copied to clipboard

AttributeError: 'Type' object has no attribute 'remove'

Open ocroquette opened this issue 6 years ago • 3 comments

I get the following error when calling one of my functions:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "python-3.7.2.amd64\lib\site-packages\pyclibrary\c_library.py", line 230, in __getattr__
    obj = self(k, n)
  File "python-3.7.2.amd64\lib\site-packages\pyclibrary\c_library.py", line 210, in __call__
    self._objs_[typ][name] = self._make_obj_(typ, name)
  File "python-3.7.2.amd64\lib\site-packages\pyclibrary\c_library.py", line 272, in _make_obj_
    return self._get_function(n)
  File "python-3.7.2.amd64\lib\site-packages\pyclibrary\c_library.py", line 338, in _get_function
    func_name, self._lock_calls_)
  File "python-3.7.2.amd64\lib\site-packages\pyclibrary\c_library.py", line 416, in __init__
    if conv in self.sig[0]:
AttributeError: 'Type' object has no attribute 'remove'

This is the corresponding code in c_library.py:

for conv in ['__stdcall', '__cdecl']:
    if conv in self.sig[0]:
        self.sig[0].remove(conv)

I added a print statement to see the value of self.sig:

print(self.sig)
[Type('int', '__stdcall'), (('d', Type('int'), None), ('p', Type('int'), None))]

As a workaround, I commented out the for loop. The error disappears and everything works as expected. I cannot judge the side-effects though.

Removing the __stdcall qualifier also prevents the issue.

The library is proprietary, so I cannot share it. But if the information provided here is not sufficient to pinpoint the issue, I can try to provide a minimal example, let me now.

ocroquette avatar Sep 09 '19 15:09 ocroquette

Wow it has been a long time since I looked at that code. It looks like the idea was (at least at one point) to avoid confusing the type with a function type by removing the qualifier. Honestly I would need to dive a bit more than I have time at the moment. I would suggest you look at the res_type attribute of the function object and figure out if it makes sense. If it does, it may mean we can actually remove that loop but I would have to dive again a bit more in the type evaluation logic.

MatthieuDartiailh avatar Sep 11 '19 22:09 MatthieuDartiailh

OK, thanks for the feedback.

ocroquette avatar Sep 12 '19 17:09 ocroquette

I had another look. The parser is fine, the problem is really in c_library. It is very easy to reproduce with a simple function like:

extern int __stdcall myfunc( void );

I have just realized that the parser has a "replace" option that makes it easy to work around the issue though:

parser = CParser([header_file],
             replace={"__stdcall": ""}
)

I tried to understand the code to fix the bug for good, but I am too unfamiliar with Python and this particular code base.

ocroquette avatar Sep 28 '19 08:09 ocroquette