Okay, I'm going to try to make this quick:
I've been doing a lot of work getting Product classes to behave in a manner that makes sense to me. In the process, I tanked some of the code metrics, and, unusually for me, I'm kind of having trouble caring about it. Basically, the various sites have a bunch of complaints, mostly around the __init_subclass__ methods, which have a lot of stuff in them because they have to do a lot of stuff. I could chop them up into smaller semi-independent bits, as I have in the past, but it's really obnoxious to navigate the file as-is, so I kind of doubt further indirection would make things clearer.
What I'm basically leaning towards in terms of architecture is that there's a thin layer of generated methods in each Product subclass, coupled with enough metadata for methods defined on the base class to dynamically change their behavior. Each subclass has to do a lot of heavy lifting to generate this metadata, so, for the time being, the methods will be big.
I'm pretty sleepy right now, so this is kind of disorganized, but I decided to try running Pylint against the code to see what I can do to improve it. As per usual, I found a bunch of weird bugs in Pylint. I guess that's the next thing to work on, filing those.
I've got maybe ten more minutes of consciousness left, though. Good night.