Personally I'm not in favor of enforcing such strict conventions, especially in a dynamic language like Python. Also isn't this pattern he repeats throughout:
class Shape:
def __init__(self, **kwds):
self.shapename = kwds.pop('shapename')
super().__init__(**kwds)
Better written like this? class Shape:
def __init__(self, shapename=None, **kwds):
self.shapename = shapename
super().__init__(**kwds)
It seems like there are some things about Python's which the author doesn't like, and he solves them by adding a lot of boiler plate to each of his classes. It's probably a better idea to just embrace the Python way or use a different language.