File: components.rst

package info (click to toggle)
circuits 3.1.0%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 9,756 kB
  • sloc: python: 15,945; makefile: 130
file content (157 lines) | stat: -rw-r--r-- 4,057 bytes parent folder | download | duplicates (2)
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.