This file is indexed.

/usr/share/doc/python-twisted-web/howto/web-in-60/session-store.html is in python-twisted-web 12.0.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
  <head>
<title>Twisted Documentation: Storing Objects in the Session</title>
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
  </head>

  <body bgcolor="white">
    <h1 class="title">Storing Objects in the Session</h1>
    <div class="toc"><ol/></div>
    <div class="content">
<span/>

<p>This example shows you how you can persist objects across requests in the
session object.</p>

<p>As was discussed <a href="session-basics.html" shape="rect">previously</a>, instances
of <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.web.server.Session.html" title="twisted.web.server.Session">Session</a></code> last as long as
the notional session itself does. Each time <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.web.server.Request.getSession.html" title="twisted.web.server.Request.getSession">Request.getSession</a></code> is called, if the session
for the request is still active, then the same <code>Session</code> instance is
returned as was returned previously. Because of this, <code>Session</code>
instances can be used to keep other objects around for as long as the session
exists.</p>

<p>It's easier to demonstrate how this works than explain it, so here's an
example:</p>

<pre class="shell" xml:space="preserve">
&gt;&gt;&gt; from zope.interface import Interface, Attribute, implements
&gt;&gt;&gt; from twisted.python.components import registerAdapter
&gt;&gt;&gt; from twisted.web.server import Session
&gt;&gt;&gt; class ICounter(Interface):
...     value = Attribute(&quot;An int value which counts up once per page view.&quot;)
...
&gt;&gt;&gt; class Counter(object):
...     implements(ICounter)
...     def __init__(self, session):
...         self.value = 0
...
&gt;&gt;&gt; registerAdapter(Counter, Session, ICounter)
&gt;&gt;&gt; ses = Session(None, None)
&gt;&gt;&gt; data = ICounter(ses)
&gt;&gt;&gt; print data
&lt;__main__.Counter object at 0x8d535ec&gt;
&gt;&gt;&gt; print data is ICounter(ses)
True
&gt;&gt;&gt;
</pre>

<p><i>What?</i>, I hear you say.</p>

<p>What's shown in this example is the interface and adaption-based
API which <code>Session</code> exposes for persisting state. There are
several critical pieces interacting here:</p>

<ul>
  <li><code>ICounter</code> is an interface which serves several purposes. Like
    all interfaces, it documents the API of some class of objects (in this case,
    just the <code>value</code> attribute). It also serves as a key into what is
    basically a dictionary within the session object: the interface is used to
    store or retrieve a value on the session (the <code>Counter</code> instance,
    in this case).</li>
  <li><code>Counter</code> is the class which actually holds the session data in
    this example. It implements <code>ICounter</code> (again, mostly for
    documentation purposes). It also has a <code>value</code> attribute, as the
    interface declared.</li>
  <li>The <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.python.components.registerAdapter.html" title="twisted.python.components.registerAdapter">registerAdapter</a></code> call sets up the
    relationship between its three arguments so that adaption will do what we
    want in this case.</li>
  <li>Adaption is performed by the expression <code>ICounter(ses)</code>. This
    is read as : adapt <code>ses</code> to <code>ICounter</code>. Because
    of the <code>registerAdapter</code> call, it is roughly equivalent
    to <code>Counter(ses)</code>. However (because of certain
    things <code>Session</code> does), it also saves the <code>Counter</code>
    instance created so that it will be returned the next time this adaption is
    done. This is why the last statement produces <code>True</code>.</li>
</ul>

<p>If you're still not clear on some of the details there, don't worry about it
and just remember this: <code>ICounter(ses)</code> gives you an object you can
persist state on. It can be as much or as little state as you want, and you can
use as few or as many different <code>Interface</code> classes as you want on a
single <code>Session</code> instance.</p>

<p>With those conceptual dependencies out of the way, it's a very short step to
actually getting persistent state into a Twisted Web application. Here's an
example which implements a simple counter, re-using the definitions from the
example above:</p>

<pre class="python"><p class="py-linenumber">1
2
3
4
5
6
7
8
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>

<span class="py-src-keyword">class</span> <span class="py-src-identifier">CounterResource</span>(<span class="py-src-parameter">Resource</span>):
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
        <span class="py-src-variable">session</span> = <span class="py-src-variable">request</span>.<span class="py-src-variable">getSession</span>()
        <span class="py-src-variable">counter</span> = <span class="py-src-variable">ICounter</span>(<span class="py-src-variable">session</span>)
        <span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span> += <span class="py-src-number">1</span>
        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;Visit #%d for you!&quot;</span> % (<span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span>,)
</pre>

<p>Pretty simple from this side, eh? All this does is
use <code>Request.getSession</code> and the adaption from above, plus some
integer math to give you a session-based visit counter.</p>

<p>Here's the complete source for an <a href="rpy-scripts.html" shape="rect">rpy script</a>
based on this example:</p>

<pre class="python"><p class="py-linenumber"> 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
</p><span class="py-src-variable">cache</span>()

<span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>, <span class="py-src-variable">Attribute</span>, <span class="py-src-variable">implements</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span>.<span class="py-src-variable">components</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">registerAdapter</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Session</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>

<span class="py-src-keyword">class</span> <span class="py-src-identifier">ICounter</span>(<span class="py-src-parameter">Interface</span>):
    <span class="py-src-variable">value</span> = <span class="py-src-variable">Attribute</span>(<span class="py-src-string">&quot;An int value which counts up once per page view.&quot;</span>)

<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
    <span class="py-src-variable">implements</span>(<span class="py-src-variable">ICounter</span>)
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">session</span>):
        <span class="py-src-variable">self</span>.<span class="py-src-variable">value</span> = <span class="py-src-number">0</span>

<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">Counter</span>, <span class="py-src-variable">Session</span>, <span class="py-src-variable">ICounter</span>)

<span class="py-src-keyword">class</span> <span class="py-src-identifier">CounterResource</span>(<span class="py-src-parameter">Resource</span>):
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
        <span class="py-src-variable">session</span> = <span class="py-src-variable">request</span>.<span class="py-src-variable">getSession</span>()
        <span class="py-src-variable">counter</span> = <span class="py-src-variable">ICounter</span>(<span class="py-src-variable">session</span>)
        <span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span> += <span class="py-src-number">1</span>
        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;Visit #%d for you!&quot;</span> % (<span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span>,)

<span class="py-src-variable">resource</span> = <span class="py-src-variable">CounterResource</span>()
</pre>

<p>One more thing to note is the <code>cache()</code> call at the top
of this example. As with the <a href="http-auth.html" shape="rect">previous
example</a> where this came up, this rpy script is stateful. This
time, it's the <code>ICounter</code> definition and
the <code>registerAdapter</code> call that need to be executed only
once. If we didn't use <code>cache</code>, every request would define
a new, different interface named <code>ICounter</code>. Each of these
would be a different key in the session, so the counter would never
get past one.</p>

</div>

    <p><a href="../index.html">Index</a></p>
    <span class="version">Version: 12.0.0</span>
  </body>
</html>