[cctbxbb] boost python and metaclass inheritance

Luc Bourhis luc_j_bourhis at mac.com
Wed Jan 8 02:05:35 PST 2014


Hi David,

I am afraid this is a dead end. Indeed scitbx.lstbx.normal_eqns.non_linear_ls is a Boost Python wrapper. What you could do instead is write:

class Refinery(object):

	def __new__(cls, *args, **kwds):
		assert cls.__bases__
		return object.__new__(cls)

class AdaptLstbx(Refinery, normal_eqns.non_linear_ls):
	pass

It is then impossible to construct an instance of Refinery. Only heirs of Refinery can be instantiated. You could make the assert more subtle to suit your needs of course.

Generally speaking, i.e. it would not apply to you, David, if you do not plan to commit metaclass-based code to the cctbx, I would strongly advise cctbx developers against using metaclasses at all. This is one of the surest way to make the code impossible to understand to your fellow programmers as it introduces highly implicit behaviour: explicit is better than implicit in the long run. 

As any rule, it has exceptions: there are 4 uses of metaclasses in the cctbx as I write this. But they are highly specialised and self-contained uses.

Best wishes,

Luc J. Bourhis

> Hi,
> 
> Does anyone know how to use __metaclass__ specification alongside inheritance from boost python classes? This code illustrates the problem:
> 
> import abc
> from scitbx.lstbx import normal_eqns
>  
> class Refinery(object):
>   __metaclass__ = abc.ABCMeta
>   pass
>  
> class AdaptLstbx(Refinery, normal_eqns.non_linear_ls):
>   pass
> 
> The result is
> 
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "/usr/lib/python2.7/abc.py", line 87, in __new__
>     cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
> TypeError: Error when calling the metaclass bases
>     metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
> 
> The real Refinery is a class that has one method that must be supplied by a concrete subclass. I like the idea of making it impossible to instantiate a base Refinery rather than relying on e.g. raise NotImplementedError() in that method definition. This is what ABCMeta would give me, if only I could get it to work here. Google found me some answers that require me to know the __metaclass__ of the bases (as suggested by the error message), but normal_eqns.non_linear_ls.__metaclass__ does not exist.
> 
> I don't terribly mind the raise NotImplementedError() alternative, but I thought that if I can easily use ABCMeta, I'd like to.
> 
> Cheers
> 
> -- David
> _______________________________________________
> cctbxbb mailing list
> cctbxbb at phenix-online.org
> http://phenix-online.org/mailman/listinfo/cctbxbb



More information about the cctbxbb mailing list