1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunclass ClassRegistryMeta(type): 6*4882a593Smuzhiyun """Give each ClassRegistry their own registry""" 7*4882a593Smuzhiyun def __init__(cls, name, bases, attrs): 8*4882a593Smuzhiyun cls.registry = {} 9*4882a593Smuzhiyun type.__init__(cls, name, bases, attrs) 10*4882a593Smuzhiyun 11*4882a593Smuzhiyunclass ClassRegistry(type, metaclass=ClassRegistryMeta): 12*4882a593Smuzhiyun """Maintain a registry of classes, indexed by name. 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunNote that this implementation requires that the names be unique, as it uses 15*4882a593Smuzhiyuna dictionary to hold the classes by name. 16*4882a593Smuzhiyun 17*4882a593SmuzhiyunThe name in the registry can be overridden via the 'name' attribute of the 18*4882a593Smuzhiyunclass, and the 'priority' attribute controls priority. The prioritized() 19*4882a593Smuzhiyunmethod returns the registered classes in priority order. 20*4882a593Smuzhiyun 21*4882a593SmuzhiyunSubclasses of ClassRegistry may define an 'implemented' property to exert 22*4882a593Smuzhiyuncontrol over whether the class will be added to the registry (e.g. to keep 23*4882a593Smuzhiyunabstract base classes out of the registry).""" 24*4882a593Smuzhiyun priority = 0 25*4882a593Smuzhiyun def __init__(cls, name, bases, attrs): 26*4882a593Smuzhiyun super(ClassRegistry, cls).__init__(name, bases, attrs) 27*4882a593Smuzhiyun try: 28*4882a593Smuzhiyun if not cls.implemented: 29*4882a593Smuzhiyun return 30*4882a593Smuzhiyun except AttributeError: 31*4882a593Smuzhiyun pass 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun try: 34*4882a593Smuzhiyun cls.name 35*4882a593Smuzhiyun except AttributeError: 36*4882a593Smuzhiyun cls.name = name 37*4882a593Smuzhiyun cls.registry[cls.name] = cls 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun @classmethod 40*4882a593Smuzhiyun def prioritized(tcls): 41*4882a593Smuzhiyun return sorted(list(tcls.registry.values()), 42*4882a593Smuzhiyun key=lambda v: (v.priority, v.name), reverse=True) 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun def unregister(cls): 45*4882a593Smuzhiyun for key in cls.registry.keys(): 46*4882a593Smuzhiyun if cls.registry[key] is cls: 47*4882a593Smuzhiyun del cls.registry[key] 48