[issue29758] Previously-working SWIG code fails in Python 3.6
Tristan Croll
report at bugs.python.org
Thu Mar 9 05:10:32 EST 2017
Tristan Croll added the comment:
OK, a further clue. First, a little more detail on how my project is arranged (to re-iterate, this works without complaint in Python 3.5):
Rather than use my SWIG output directly, I've created a further wrapper layer in Python to add functions/syntactic sugar that would be difficult to achieve in SWIG, add a bit of extra documentation, and bury some classes that may be occasionally useful but don't really need to be in the primary API. The SWIG output Python library I name clipper_core, and I use the following class decorators for classes in the front-end API to reduce the amount of code (Python and SWIG) needed:
def mappedclass(old_cls):
'''
Ensures that objects returned from functions in the clipper_core
library are instantiated in Python as the derived class with the
extra functionality.
'''
def decorator(cls):
def __newnew__(thiscls, *args, **kwargs):
if thiscls == old_cls:
return object.__new__(cls)
return object.__new__(thiscls)
old_cls.__new__ = __newnew__
return cls
return decorator
def getters_to_properties(*funcs):
'''
Class decorator. Add the names of any getter functions with void
arguments (e.g. Coord_grid.u()) to convert them to properties. If
you want the property name to be different from the function name,
add the desired name and the function name as a tuple
(e.g. ('uvw', '_get_uvw'))
'''
def property_factory(func):
def getter(self):
return getattr(super(self.__class__, self), func)()
prop = property(getter)
return prop
def decorator(cls):
for func in funcs:
if type(func) == tuple:
setattr(cls, func[0], property_factory(func[1]))
else:
setattr(cls, func, property_factory(func))
return cls
return decorator
def format_to_string(cls):
'''
Class decorator to redirect the Clipper format() function to __str__,
to provide pretty printing of the object.
'''
def format(self):
return super(self.__class__,self).format()
def __str__(self):
return self.format
setattr(cls, 'format', property(format))
setattr(cls, '__str__', __str__)
return cls
Experimenting this morning with the following two classes:
@format_to_string
@mappedclass(clipper_core.Cell_descr)
class Cell_descr(clipper_core.Cell_descr):
def __init__(self, abc, angles):
'''
__init__(self, abc, angles) -> Cell_descr
Args:
abc ([float*3]): cell dimensions in Angstroms
angles ([float*3]): alpha, beta and gamma angles in degrees
'''
clipper_core.Cell_descr.__init__(self, *abc, *angles)
@format_to_string
@getters_to_properties('cell_descr', 'matrix_frac', 'matrix_orth',
'metric_real', 'metric_reci', 'volume')
@mappedclass(clipper_core.Cell)
class Cell(clipper_core.Cell):
'''
Define a crystallographic unit cell using the lengths of the three
sides a, b, c (in Angstroms) and the three angles alpha, beta, gamma
(in degrees).
'''
def __init__(self, abc, angles):
'''
__init__(self, abc, angles) -> Cell
Args:
abc ([float*3]): cell dimensions in Angstroms
angles ([float*3]): alpha, beta and gamma angles in degrees
'''
cell_descr = Cell_descr(abc, angles)
#cell_descr = clipper_core.Cell_descr(*abc, *angles)
clipper_core.Cell.__init__(self, cell_descr)
def __eq__(self, other):
return self.equals(other)
Then:
import clipper
cell = clipper.cell([100,100,100],[90,90,90])
cell.cell_descr
SystemError Traceback (most recent call last)
<ipython-input-4-c5072ce3ae97> in <module>()
----> 1 c.cell_descr
/home/tic20/apps/chimerax/lib/python3.6/site-packages/chimerax/clipper/clipper_decorators.py in getter(self)
87 def property_factory(func):
88 def getter(self):
---> 89 return getattr(super(self.__class__, self), func)()
90 prop = property(getter)
91 return prop
/home/tic20/apps/chimerax/lib/python3.6/site-packages/chimerax/clipper/lib/clipper_python_core/clipper.py in cell_descr(self)
8249
8250 """
-> 8251 return _clipper.Cell_cell_descr(self)
8252
8253 __swig_destroy__ = _clipper.delete_Cell
SystemError: Objects/tupleobject.c:81: bad argument to internal function
... but if I comment out the derived Cell_descr class and switch to the alternate cell_descr constructor in Cell.__init__(), then it works as expected. I have tried commenting out the other class decorators, with no effect - so it would seem it's what's happening in the @mappedclass decorator that is causing my troubles.
----------
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue29758>
_______________________________________
More information about the Python-bugs-list
mailing list