1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
.. module:: circuits.core.components
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
:class:`~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
:class:`circuits.web.servers.Server` Component which is comprised of:
- :class:`circuits.net.sockets.TCPServer`
- :class:`circuits.web.servers.BaseServer`
- :class:`circuits.web.http.HTTP`
- :class:`circuits.web.dispatchers.dispatcher.Dispatcher`
.. 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:
- :meth:`~BaseComponent.register`
- :meth:`~BaseComponent.unregister`
Component Registration
----------------------
To register a component use the :meth:`~Component.register` method.
.. code-block:: python
:linenos:
from circuits import Component
class Foo(Component):
"""Foo Component"""
class App(Component):
"""App Component"""
def init(self):
Foo().register(self)
app = App()
debugger = Debugger().register(app)
app.run()
Unregistering Components
------------------------
Components are unregistered via the :meth:`~Component.unregister` method.
.. code-block:: python
debugger.unregister()
.. note:: You need a reference to the component you wish to
unregister. The :meth:`~Component.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 :meth:`~Component.register` and
:meth:`~Component.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:
- :meth:`~Component.register` map to ``+`` and ``+=``
- :meth:`~Component.unregister` map to> ``-`` and ``-=``
For example the above could have been written as:
.. code-block:: python
:linenos:
from circuits import Component
class Foo(Component):
"""Foo Component"""
class App(Component):
"""App Component"""
def init(self):
self += Foo()
(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:
.. code-block:: python
>>> 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 <https://bitbucket.org/circuits/circuits/src/tip/examples/telnet.py>`_
does this for example.
|