# Pyramid events tracing
###### tags: `SED`
In the module, event, there are a [subsciber](#Subscriber) class and six [event types](#[EventType]).
ContextFound is assigned as AfterTraversal
ApplicationCreated is assigned as WSGIApplicationCreatedEvent
```graphviz
digraph hierarchy {
node [shape=record]
Sub[label="{
Subscriber|
-venusian: venusian\l
-ifcas\l
-predicates\l
-depth\l
-category\l
|
+__init__()\l
+register()\l
+call()\l
}"]
Sub->venusian[arrowhead=vee]
}
```
```graphviz
digraph hierarchy {
node [shape=record]
Irequest[label="{
\<\<interface\>\>\nINewRequest
}"]
request[label="{
NewRequest|
-request\l|
+__init__()\l
}"]
Irequest->request[dir=back, style=dashed, arrowtail=onormal]
Iresponse[label="{
\<\<interface\>\>\nINewResponse
}"]
response[label="{
NewResponse|
-request\l
-response\l|
+__init__()\l
}"]
Iresponse->response[dir=back, style=dashed, arrowtail=onormal]
Itraverse[label="{
\<\<interface\>\>\nIBeforeTraversal
}"]
traverse[label="{
BeforeTraversal|
-request\l|
+__init__()\l
}"]
Itraverse->traverse[dir=back, style=dashed, arrowtail=onormal]
}
```
```graphviz
digraph hierarchy {
node [shape=record]
Icontext[label="{
\<\<interface\>\>\nIContextFound
}"]
context[label="{
ContextFound|
-request\l|
+__init__()\l
}"]
Icontext->context[dir=back, style=dashed, arrowtail=onormal]
Iapp[label="{
\<\<interface\>\>\nIApplicationCreated
}"]
app[label="{
ApplicationCreated|
-app\l
-object\l|
+__init__()\l
}"]
Iapp->app[dir=back, style=dashed, arrowtail=onormal]
Irender[label="{
\<\<interface\>\>\nIBeforeRender
}"]
render[label="{
BeforeRender|
-dict\l
-render_val\l|
+__init__()\l
}"]
Irender->render[dir=back, style=dashed, arrowtail=onormal]
}
```
## Who called events?
### Router
```graphviz
digraph hierarchy {
node [shape=record]
router[label="{
Router|
-registry\l|
+handle_request()\l
+invoke_request()\l
}"]
router->ContextFound[style=dashed, arrowhead=vee, label="<<use>>"]
router->NewRequest[style=dashed, arrowhead=vee, label="<<use>>"]
router->NewResponse[style=dashed, arrowhead=vee, label="<<use>>"]
router->BeforeTraversal[style=dashed, arrowhead=vee, label="<<use>>"]
registry[label="{registry||+notify()}"]
router->registry[arrowhead=vee]
}
```
```c++
handle_request(){
notify = registry.notify;
notify(NewRequest(request));
...
notify(BeforeTraversal(request));
...
notify(ContextFound(request));
}
```
```c++
invoke_request(){
notify = registry.notify;
notify(NewResponse(request, response));
}
```
### Configurator
```graphviz
digraph hierarchy{
node [shape=record]
Configurator->ApplicationCreated[style=dashed, arrowhead=vee, label="<<use>>"]
registry[label="{registry||+notify()}"]
Configurator->registry[arrowhead=vee]
}
```
```c++
make_wsgi_app(){
...
app = Router(self.registry);
...
self.registry.notify(ApplicationCreated(app));
...
}
```
### Renderers
```graphviz
digraph hierarchy{
node [shape=record]
renderH[label="{
RendererHelper|
|
+__init__()\l
+settings()\l
+renderer()\l
+get_renderer()\l
+render_view()\l
+render()\l
+render_to_response()\l
-make_response()\l
+clone()\l
}"]
renderH->BeforeRender[style=dashed, arrowhead=vee, label="<<use>>"]
registry[label="{registry||+notify()}"]
renderH->registry[arrowhead=vee]
}
```
```c++
render(value, system_values, request){
...
system_values = BeforeRender(system_values, value);
registry = self.registry
registry.notify(system_values);
}
```
```graphviz
digraph hierarchy {
node [shape=record]
Irequest[label="{
\<\<interface\>\>\nINewRequest
}"]
request[label="{
NewRequest|
-request\l|
+__init__()\l
}"]
Irequest->request[dir=back, style=dashed, arrowtail=onormal]
Iresponse[label="{
\<\<interface\>\>\nINewResponse
}"]
response[label="{
NewResponse|
-request\l
-response\l|
+__init__()\l
}"]
Iresponse->response[dir=back, style=dashed, arrowtail=onormal]
Itraverse[label="{
\<\<interface\>\>\nIBeforeTraversal
}"]
traverse[label="{
BeforeTraversal|
-request\l|
+__init__()\l
}"]
Itraverse->traverse[dir=back, style=dashed, arrowtail=onormal]
Icontext[label="{
\<\<interface\>\>\nIContextFound
}"]
context[label="{
ContextFound|
-request\l|
+__init__()\l
}"]
Icontext->context[dir=back, style=dashed, arrowtail=onormal]
Iapp[label="{
\<\<interface\>\>\nIApplicationCreated
}"]
app[label="{
ApplicationCreated|
-app\l
-object\l|
+__init__()\l
}"]
Iapp->app[dir=back, style=dashed, arrowtail=onormal]
Irender[label="{
\<\<interface\>\>\nIBeforeRender
}"]
render[label="{
BeforeRender|
-dict\l
-render_val\l|
+__init__()\l
}"]
Irender->render[dir=back, style=dashed, arrowtail=onormal]
router[label="{
Router|
-registry\l|
+handle_request()\l
+invoke_request()\l
}"]
router->context[style=dashed, arrowhead=vee, label="<<use>>"]
router->request[style=dashed, arrowhead=vee, label="<<use>>"]
router->response[style=dashed, arrowhead=vee, label="<<use>>"]
router->traverse[style=dashed, arrowhead=vee, label="<<use>>"]
router->registry[arrowhead=vee]
Configurator->app[style=dashed, arrowhead=vee, label="<<use>>"]
Configurator->registry[arrowhead=vee]
renderH[label="{
RendererHelper|
|
+__init__()\l
+settings()\l
+renderer()\l
+get_renderer()\l
+render_view()\l
+render()\l
+render_to_response()\l
-make_response()\l
+clone()\l
}"]
renderH->render[style=dashed, arrowhead=vee, label="<<use>>"]
renderH->registry[arrowhead=vee]
registry[label="{registry||+notify()}"]
}
```
## [EventType]
EventType are types that implemented the corresponding InterfaceEventType.
```mermaid
graph TD
A(EventType)-->B(zope.interface.declaration::implementer)
A-->C(InterfaceEventType<br>pyramid.interfaces)
E(zope.interface.Interface)---|include|C
C-->D(zope.interface.Attribute)
style A fill:#f9f
style C fill:#f9f
```
```python
@implementer([InterfaceEventType])
class [EventType](object):
```
Make the class, [EventType], implements the interface, [InterfaceEventType].
* [implementer](#implementer)
* [InterfaceEventType](#InterfaceEventType)
### implementer
zope/interface/declaration.py
```python
def __call__(self, ob):
if isinstance(ob, *):
classImplements(ob, interfaces)
else:
Implements.named(*, interfaces)
```
* [classImplements](#)
* [Implements.named](#)
### InterfaceEventType
pyramid/interfaces.py
```python
class [InterfaceEventType](Interface):
[variable] = Attribute([SomeString])
```
This class inherents from the basic class, Interface, from zope.interface.Interface.
* [Interface](#Interface)
* [Attribute](#Attribute)
### Attribute
zope/interface/interface.py
```python
class Attribute:
interface = None
classImplements(Attribute, IAttribute)
```
### Interface
zope/interface/interface.py
```python
Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
```
## Subscriber
Called as a decorator, the subscriber used the package, Venusian, to defer the decorator behavior.
```mermaid
graph TD
A(subscriber)---|method|B(__init__)
A---|method|C(__call__)
A---|method|D(register)
C-->D
```
### subscriber.\__call\__ and subscriber.register
Upon called, the register for a certain event is attached to venusian wait until `pyramid.config.Configurator().scan()` is called.
```python
def register():
...
config.add_subscriber(...)
def __call__():
self.venusian.attach(
wrapped,
self.register,
category=self.category,
depth=self.depth + 1,
)
```
## Example
* To use subscriber
* To customize events
### To use subscriber
form: https://glitch.com/~pyramid-events-subscribers
```python
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.events import NewRequest
from pyramid.events import NewResponse
from pyramid.events import subscriber
from pyramid.response import Response
from pyramid.view import view_config
@view_config(
route_name='home',
)
def home(request):
return Response('Welcome!')
@subscriber(NewRequest, NewResponse)
def mysubscriber(event):
print(event)
if __name__ == '__main__':
with Configurator() as config:
config.add_route('home', '/')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 3000, app)
server.serve_forever()
```
### To customize events
from: https://docs.pylonsproject.org/projects/pyramid/en/latest/api/events.html
```python
class DocCreated(object):
def __init__(self, doc, request):
self.doc = doc
self.request = request
from pyramid.events import subscriber
@subscriber(DocCreated)
def index_doc(event):
# index the document using our application's index_doc function
doSomething(event.doc, event.request)
def new_doc_view(request):
doc = MyDoc()
event = DocCreated(doc, request)
request.registry.notify(event)
return {'document': doc}
```
## References
* [pyramid event document 1](https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/events.html)
* [pyramid event document 2](https://docs.pylonsproject.org/projects/pyramid/en/latest/api/events.html)
* [venusian document](https://buildmedia.readthedocs.org/media/pdf/venusian/latest/venusian.pdf)
* [zope.interface example](https://stackoverflow.com/questions/2521189/purpose-of-zope-interfaces)
* [pyramid subscriber example](https://glitch.com/~pyramid-events-subscribers)