Simple Dictionary of Objects

With a Kickin’ Useful AutoRegister Metaclass

Many applications need some sort of dictionary that maps string names to objects. This is ours.


The simplest possible use is really not much more than a dictionary:

import base

class MyClass:

base.registry.Register(MyClass, 'some_name')

assert(base.registry.Get('some_name') == MyClass)

You can register instances if you’d prefer:

base.registry.Register(MyClass(), 'some_name')

assert(isinstance(base.registry.Get('some_name'), MyClass))

Default Object Names

If you don’t provide a name for the registered object, we’ll use base.utils.ObjectName() instead. This is a two-part name with a single dot:

  • module_name.class_name

If all your code is in one file, your module_name is “__main__”, which is not interesting. But if your code is split across separate modules, the module’s name is probably what you expect.

Imagine a file that contains:

import base

class MyClass:


While the file contains:

import base
import mymodule


Running python3 would print:

<class 'mymodule.MyClass'>

The name is always two-part. If objects are defined in sub-modules, only the top-level module’s name is used. Said another way, they Python class mymodule.mysubmodule.mysubsubmodule.MyClass would be known to us only as: “mymodule.MyClass

Metaclass AutoRegister

The true joy of our registry is our AutoRegister metaclass.

class MyBaseClass(metaclass=base.registry.AutoRegister):

class MySubClass(MyBaseClass):

Here, both MyBaseClass and MySubClass are both registered automatically.

AutoRegister Options

The AutoRegister metaclass takes a few optional arguments:

  • skipinteger – default=0 – number of levels NOT to register
  • instancesboolean – default=False – register an instance of each class rather than the class itself
  • regnamestring – default=None – name of a property on your class from which to get the registry name


The skip argument causes some number of higher-level classes to not be registered, while deeper sub-classes still get registered.

For example:

class MyBaseClass(metaclass=base.registry.AutoRegister, skip=1):

class MySubClass(MyBaseClass):

Here, MyBaseClass is not registered, while MySubClass does get registered.


The instances, if set True, then an instance of each of your classes gets registered instead of the class itself.


You can specify a property on your class that gets used to find a registry name.

For example:

class MyClass(metaclass=base.registry.AutoRegister, regname='slug'):
  def slug(self):
    return base.utils.Slugify(base.utils.ClassName(self))

Here, the registered name will be “myclass” (the slugified class name) rather than “__main__.MyClass” (the full object name).

Note: this example uses our @base.utils.anyproperty decorator, which is like a @property that can be called on the class itself as well as instances of that class.

Back to “OctoBase”