Fix Version/s: None
Team:Data Release Production
Our codebase is full of template classes that are wrapped into a set of Python classes with suffixes derived from their template type (e.g. ImageF, ImageD, ImageU).
In some places, we've defined a module scoped dictionary with the un-suffixed name to relate these, e.g. afw.table.Key["F"] is afw.table.KeyF.
To enhance both the usuability of our Python interfaces and the ease of writing wrappers, we should:
- Add an Abstract Base Class for each of these template classes (https://docs.python.org/2/library/abc.html), making it appear as though all template instantiations inherit from the same class (in e.g. isinstance checks).
- Make these ABCs inherit from a custom metaclass (which in turn inherits from abc.ABCMeta) that allows dict-like access to the registered instantiations from both the string suffixes and the corresponding numpy types (e.g. numpy.float32 for "F"), preserving the dict behavior mentioned above.
- Add a __new__ method to each ABC that accepts a dtype argument and forwards all other arguments to the constructor of the wrapped template the dtype key points to. In other words, make e.g. Image(bbox, dtype=numpy.float32) call ImageF(bbox). We could probably have the metaclass inject this automatically.
New users to the stack should be able to mostly get by without seeing the templated types at all - they'd only interact with the ABC. And devs writing the Python wrappers for templated classes could define pure-Python extensions directly in the ABC instead of monkeypatching them into each wrapped template.
This issue covers adding the metaclass to utils and demonstrating its use in at least one template class wrapper. Using it for other classes could be done on other pybind11 branches, as it strictly represents an addition to the API, and it could be useful to do it there as to get the monkeypatching-avoidance mentioned above.
In addition to the above, this ticket should include an implementation for the decorators described in
RFC-270, which have significant code in common with the metaclass (as implemented currently) and a related purpose.