Components

The architectural concept of circuits is to encapsulate system functionality into discrete manageable and reusable units, called Components, that interact by sending and handling events that flow throughout the system.

Technically, a circuits Component is a Python class that inherits (directly or indirectly) from BaseComponent.

Components can be sub-classed like any other normal Python class, however components can also be composed of other components and it is natural to do so. These are called Complex Components. An example of a Complex Component within the circuits library is the circuits.web.servers.Server Component which is comprised of:

Note

There is no class or other technical means to mark a component as a complex component. Rather, all component instances in a circuits based application belong to some component tree (there may be several), with Complex Components being a subtree within that structure.

A Component is attached to the tree by registering with the parent and detached by unregistering itself. See methods:

The hierarchy of components facilitates addition and removal of complex components at runtime.

All registered components in the hierarchy receive all applicable events regardless of lineage.

Component Registration

To register a component use the register() method.

 1from circuits import Component
 2
 3
 4class Foo(Component):
 5    """Foo Component"""
 6
 7
 8class  App(Component):
 9    """App Component"""
10
11    def init(self):
12        Foo().register(self)
13
14
15app = App()
16debugger = Debugger().register(app)
17app.run()

Unregistering Components

Components are unregistered via the unregister() method.

debugger.unregister()

Note

You need a reference to the component you wish to unregister. The register() method returns you a reference of the component that was registered.

Convenient Shorthand Form

After a while when your application becomes rather large and complex with many components and component registrations you will find it cumbersome to type .register(blah).

circuits has several convenient methods for component registration and deregistration that work in an identical fashion to their register() and unregister() counterparts.

These convenience methods follow normal mathematical operator precedence rules and are implemented by overloading the Python __add__, __iadd__, __sub__ and __isub__.

The mapping is as follow:

  • register() map to + and +=

  • unregister() map to> - and -=

For example the above could have been written as:

 1from circuits import Component
 2
 3
 4class Foo(Component):
 5    """Foo Component"""
 6
 7
 8class  App(Component):
 9    """App Component"""
10
11    def init(self):
12        self += Foo()
13
14
15(App() + Debugger()).run()

Implicit Component Registration(s)

Sometimes it’s handy to implicitly register components into another component by simply referencing the other component instance as a class attribute of the other.

Example:

>>> from circuits import Component
>>>
>>> class Foo(Component):
...     """Foo Component"""
...
>>> class App(Component):
...     """App Component"""
...
...     foo = Foo()
...
>>> app = App()
>>> app.components
set([<Foo/* 28599:MainThread (queued=0) [S]>])
>>>

The telnet Example does this for example.