File: versioned_map.html

package info (click to toggle)
sqlalchemy 0.9.8%2Bdfsg-0.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 23,952 kB
  • ctags: 24,534
  • sloc: python: 152,282; ansic: 1,346; makefile: 257; xml: 17
file content (420 lines) | stat: -rw-r--r-- 34,165 bytes parent folder | download
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        
        <title>
            
    
                examples.versioned_rows.versioned_map
             &mdash;
    SQLAlchemy 0.9 Documentation

        </title>

        
            <!-- begin iterate through SQLA + sphinx environment css_files -->
                <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
                <link rel="stylesheet" href="../../../_static/docs.css" type="text/css" />
                <link rel="stylesheet" href="../../../_static/sphinx_paramlinks.css" type="text/css" />
                <link rel="stylesheet" href="../../../_static/changelog.css" type="text/css" />
            <!-- end iterate through SQLA + sphinx environment css_files -->
        

        

    

    <!-- begin layout.mako headers -->

    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
          URL_ROOT:    '../../../',
          VERSION:     '0.9.8',
          COLLAPSE_MODINDEX: false,
          FILE_SUFFIX: '.html'
      };
    </script>

    <!-- begin iterate through sphinx environment script_files -->
        <script type="text/javascript" src="../../../_static/jquery.js"></script>
        <script type="text/javascript" src="../../../_static/underscore.js"></script>
        <script type="text/javascript" src="../../../_static/doctools.js"></script>
    <!-- end iterate through sphinx environment script_files -->

    <script type="text/javascript" src="../../../_static/detectmobile.js"></script>
    <script type="text/javascript" src="../../../_static/init.js"></script>
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.html" />
        <link rel="copyright" title="Copyright" href="../../../copyright.html" />
    <link rel="top" title="SQLAlchemy 0.9 Documentation" href="../../../index.html" />
        <link rel="up" title="Module code" href="../../index.html" />
    <!-- end layout.mako headers -->


    </head>
    <body>
        















<div id="docs-container">





<div id="docs-top-navigation-container" class="body-background">
<div id="docs-header">
    <div id="docs-version-header">
        Release: <span class="version-num">0.9.8</span> | Release Date: October 13, 2014
    </div>

    <h1>SQLAlchemy 0.9 Documentation</h1>

</div>
</div>

<div id="docs-body-container">

    <div id="fixed-sidebar" class="">

        <div id="index-nav">
            <form class="search" action="../../../search.html" method="get">
              <input type="text" name="q" size="12" /> <input type="submit" value="Search" />
              <input type="hidden" name="check_keywords" value="yes" />
              <input type="hidden" name="area" value="default" />
            </form>

            <p>
            <a href="../../../index.html">Contents</a> |
            <a href="../../../genindex.html">Index</a>
            </p>

        </div>


    </div>

    

    <div id="docs-body" class="" >
        
<h1>Source code for examples.versioned_rows.versioned_map</h1><div class="highlight"><pre>
<span class="sd">&quot;&quot;&quot;A variant of the versioned_rows example. Here</span>
<span class="sd">we store a dictionary of key/value pairs, storing the k/v&#39;s in a</span>
<span class="sd">&quot;vertical&quot; fashion where each key gets a row. The value is split out</span>
<span class="sd">into two separate datatypes, string and int - the range of datatype</span>
<span class="sd">storage can be adjusted for individual needs.</span>

<span class="sd">Changes to the &quot;data&quot; attribute of a ConfigData object result in the</span>
<span class="sd">ConfigData object being copied into a new one, and new associations to</span>
<span class="sd">its data are created. Values which aren&#39;t changed between versions are</span>
<span class="sd">referenced by both the former and the newer ConfigData object.</span>
<span class="sd">Overall, only INSERT statements are emitted - no rows are UPDATed or</span>
<span class="sd">DELETEd.</span>

<span class="sd">An optional feature is also illustrated which associates individual</span>
<span class="sd">key/value pairs with the ConfigData object in which it first</span>
<span class="sd">originated. Since a new row is only persisted when a new value is</span>
<span class="sd">created for a particular key, the recipe provides a way to query among</span>
<span class="sd">the full series of changes which occurred for any particular key in</span>
<span class="sd">the dictionary.</span>

<span class="sd">The set of all ConfigData in a particular table represents a single</span>
<span class="sd">series of versions. By adding additional columns to ConfigData, the</span>
<span class="sd">system can be made to store multiple version streams distinguished by</span>
<span class="sd">those additional values.</span>

<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="kn">import</span> <span class="n">Column</span><span class="p">,</span> <span class="n">String</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">,</span> \
    <span class="n">create_engine</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm.interfaces</span> <span class="kn">import</span> <span class="n">SessionExtension</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">attributes</span><span class="p">,</span> <span class="n">relationship</span><span class="p">,</span> <span class="n">backref</span><span class="p">,</span> \
    <span class="n">sessionmaker</span><span class="p">,</span> <span class="n">make_transient</span><span class="p">,</span> <span class="n">validates</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.associationproxy</span> <span class="kn">import</span> <span class="n">association_proxy</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm.collections</span> <span class="kn">import</span> <span class="n">attribute_mapped_collection</span>

<span class="k">class</span> <span class="nc">VersionExtension</span><span class="p">(</span><span class="n">SessionExtension</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Apply the new_version() method of objects which are</span>
<span class="sd">    marked as dirty during a flush.</span>

<span class="sd">    See http://www.sqlalchemy.org/trac/wiki/UsageRecipes/VersionedRows</span>

<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">def</span> <span class="nf">before_flush</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">flush_context</span><span class="p">,</span> <span class="n">instances</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">instance</span> <span class="ow">in</span> <span class="n">session</span><span class="o">.</span><span class="n">dirty</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">instance</span><span class="p">,</span> <span class="s">&#39;new_version&#39;</span><span class="p">)</span> <span class="ow">and</span> \
                <span class="n">session</span><span class="o">.</span><span class="n">is_modified</span><span class="p">(</span><span class="n">instance</span><span class="p">,</span> <span class="n">passive</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>

                <span class="c"># make it transient</span>
                <span class="n">instance</span><span class="o">.</span><span class="n">new_version</span><span class="p">(</span><span class="n">session</span><span class="p">)</span>

                <span class="c"># re-add</span>
                <span class="n">session</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">instance</span><span class="p">)</span>

<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">ConfigData</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Represent a series of key/value pairs.</span>

<span class="sd">    ConfigData will generate a new version of itself</span>
<span class="sd">    upon change.</span>

<span class="sd">    The &quot;data&quot; dictionary provides access via</span>
<span class="sd">    string name mapped to a string/int value.</span>

<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">&#39;config&#39;</span>

    <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Primary key column of this ConfigData.&quot;&quot;&quot;</span>

    <span class="n">elements</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">&quot;ConfigValueAssociation&quot;</span><span class="p">,</span>
                    <span class="n">collection_class</span><span class="o">=</span><span class="n">attribute_mapped_collection</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">),</span>
                    <span class="n">backref</span><span class="o">=</span><span class="n">backref</span><span class="p">(</span><span class="s">&quot;config_data&quot;</span><span class="p">),</span>
                    <span class="n">lazy</span><span class="o">=</span><span class="s">&quot;subquery&quot;</span>
                <span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Dictionary-backed collection of ConfigValueAssociation objects,</span>
<span class="sd">    keyed to the name of the associated ConfigValue.</span>

<span class="sd">    Note there&#39;s no &quot;cascade&quot; here.  ConfigValueAssociation objects</span>
<span class="sd">    are never deleted or changed.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">_new_value</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Create a new entry for usage in the &#39;elements&#39; dictionary.&quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">ConfigValueAssociation</span><span class="p">(</span><span class="n">ConfigValue</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span>

    <span class="n">data</span> <span class="o">=</span> <span class="n">association_proxy</span><span class="p">(</span><span class="s">&quot;elements&quot;</span><span class="p">,</span> <span class="s">&quot;value&quot;</span><span class="p">,</span> <span class="n">creator</span><span class="o">=</span><span class="n">_new_value</span><span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Proxy to the &#39;value&#39; elements of each related ConfigValue,</span>
<span class="sd">    via the &#39;elements&#39; dictionary.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">data</span>

    <span class="nd">@validates</span><span class="p">(</span><span class="s">&#39;elements&#39;</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">_associate_with_element</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">element</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Associate incoming ConfigValues with this</span>
<span class="sd">        ConfigData, if not already associated.</span>

<span class="sd">        This is an optional feature which allows</span>
<span class="sd">        more comprehensive history tracking.</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">element</span><span class="o">.</span><span class="n">config_value</span><span class="o">.</span><span class="n">originating_config</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">element</span><span class="o">.</span><span class="n">config_value</span><span class="o">.</span><span class="n">originating_config</span> <span class="o">=</span> <span class="bp">self</span>
        <span class="k">return</span> <span class="n">element</span>

    <span class="k">def</span> <span class="nf">new_version</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
        <span class="c"># convert to an INSERT</span>
        <span class="n">make_transient</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="bp">None</span>

        <span class="c"># history of the &#39;elements&#39; collection.</span>
        <span class="c"># this is a tuple of groups: (added, unchanged, deleted)</span>
        <span class="n">hist</span> <span class="o">=</span> <span class="n">attributes</span><span class="o">.</span><span class="n">get_history</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;elements&#39;</span><span class="p">)</span>

        <span class="c"># rewrite the &#39;elements&#39; collection</span>
        <span class="c"># from scratch, removing all history</span>
        <span class="n">attributes</span><span class="o">.</span><span class="n">set_committed_value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">&#39;elements&#39;</span><span class="p">,</span> <span class="p">{})</span>

        <span class="c"># new elements in the &quot;added&quot; group</span>
        <span class="c"># are moved to our new collection.</span>
        <span class="k">for</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">hist</span><span class="o">.</span><span class="n">added</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">elements</span><span class="p">[</span><span class="n">elem</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">elem</span>

        <span class="c"># copy elements in the &#39;unchanged&#39; group.</span>
        <span class="c"># the new ones associate with the new ConfigData,</span>
        <span class="c"># the old ones stay associated with the old ConfigData</span>
        <span class="k">for</span> <span class="n">elem</span> <span class="ow">in</span> <span class="n">hist</span><span class="o">.</span><span class="n">unchanged</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">elements</span><span class="p">[</span><span class="n">elem</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ConfigValueAssociation</span><span class="p">(</span><span class="n">elem</span><span class="o">.</span><span class="n">config_value</span><span class="p">)</span>

        <span class="c"># we also need to expire changes on each ConfigValueAssociation</span>
        <span class="c"># that is to remain associated with the old ConfigData.</span>
        <span class="c"># Here, each one takes care of that in its new_version()</span>
        <span class="c"># method, though we could do that here as well.</span>


<span class="k">class</span> <span class="nc">ConfigValueAssociation</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Relate ConfigData objects to associated ConfigValue objects.&quot;&quot;&quot;</span>

    <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">&#39;config_value_association&#39;</span>

    <span class="n">config_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">ForeignKey</span><span class="p">(</span><span class="s">&#39;config.id&#39;</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Reference the primary key of the ConfigData object.&quot;&quot;&quot;</span>


    <span class="n">config_value_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">ForeignKey</span><span class="p">(</span><span class="s">&#39;config_value.id&#39;</span><span class="p">),</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Reference the primary key of the ConfigValue object.&quot;&quot;&quot;</span>

    <span class="n">config_value</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">&quot;ConfigValue&quot;</span><span class="p">,</span> <span class="n">lazy</span><span class="o">=</span><span class="s">&quot;joined&quot;</span><span class="p">,</span> <span class="n">innerjoin</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Reference the related ConfigValue object.&quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">config_value</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">config_value</span> <span class="o">=</span> <span class="n">config_value</span>

    <span class="k">def</span> <span class="nf">new_version</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Expire all pending state, as ConfigValueAssociation is immutable.&quot;&quot;&quot;</span>

        <span class="n">session</span><span class="o">.</span><span class="n">expire</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">config_value</span><span class="o">.</span><span class="n">name</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">config_value</span><span class="o">.</span><span class="n">value</span>

    <span class="nd">@value.setter</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Intercept set events.</span>

<span class="sd">        Create a new ConfigValueAssociation upon change,</span>
<span class="sd">        replacing this one in the parent ConfigData&#39;s dictionary.</span>

<span class="sd">        If no net change, do nothing.</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">value</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">config_value</span><span class="o">.</span><span class="n">value</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">config_data</span><span class="o">.</span><span class="n">elements</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> \
                    <span class="n">ConfigValueAssociation</span><span class="p">(</span>
                        <span class="n">ConfigValue</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config_value</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
                    <span class="p">)</span>

<span class="k">class</span> <span class="nc">ConfigValue</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Represent an individual key/value pair at a given point in time.</span>

<span class="sd">    ConfigValue is immutable.</span>

<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">&#39;config_value&#39;</span>

    <span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span> <span class="n">nullable</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
    <span class="n">originating_config_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">&#39;config.id&#39;</span><span class="p">),</span>
                            <span class="n">nullable</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
    <span class="n">int_value</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">)</span>
    <span class="n">string_value</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">255</span><span class="p">))</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>

    <span class="n">originating_config</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">&quot;ConfigData&quot;</span><span class="p">)</span>
    <span class="sd">&quot;&quot;&quot;Reference to the originating ConfigData.</span>

<span class="sd">    This is optional, and allows history tracking of</span>
<span class="sd">    individual values.</span>

<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">new_version</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s">&quot;ConfigValue is immutable.&quot;</span><span class="p">)</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;int_value&#39;</span><span class="p">,</span> <span class="s">&#39;string_value&#39;</span><span class="p">):</span>
            <span class="n">v</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">v</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">v</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">None</span>

    <span class="nd">@value.setter</span>
    <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">int_value</span> <span class="o">=</span> <span class="n">value</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">string_value</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">string_value</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">int_value</span> <span class="o">=</span> <span class="bp">None</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s">&#39;sqlite://&#39;</span><span class="p">,</span> <span class="n">echo</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
    <span class="n">Session</span> <span class="o">=</span> <span class="n">sessionmaker</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">,</span> <span class="n">extension</span><span class="o">=</span><span class="n">VersionExtension</span><span class="p">())</span>

    <span class="n">sess</span> <span class="o">=</span> <span class="n">Session</span><span class="p">()</span>

    <span class="n">config</span> <span class="o">=</span> <span class="n">ConfigData</span><span class="p">({</span>
        <span class="s">&#39;user_name&#39;</span><span class="p">:</span><span class="s">&#39;twitter&#39;</span><span class="p">,</span>
        <span class="s">&#39;hash_id&#39;</span><span class="p">:</span><span class="s">&#39;4fedffca37eaf&#39;</span><span class="p">,</span>
        <span class="s">&#39;x&#39;</span><span class="p">:</span><span class="mi">27</span><span class="p">,</span>
        <span class="s">&#39;y&#39;</span><span class="p">:</span><span class="mi">450</span>
        <span class="p">})</span>

    <span class="n">sess</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">config</span><span class="p">)</span>
    <span class="n">sess</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
    <span class="n">version_one</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">id</span>

    <span class="n">config</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="s">&#39;user_name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;yahoo&#39;</span>
    <span class="n">sess</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>

    <span class="n">version_two</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">id</span>

    <span class="k">assert</span> <span class="n">version_one</span> <span class="o">!=</span> <span class="n">version_two</span>

    <span class="c"># two versions have been created.</span>

    <span class="k">assert</span> <span class="n">config</span><span class="o">.</span><span class="n">data</span> <span class="o">==</span> <span class="p">{</span>
        <span class="s">&#39;user_name&#39;</span><span class="p">:</span><span class="s">&#39;yahoo&#39;</span><span class="p">,</span>
        <span class="s">&#39;hash_id&#39;</span><span class="p">:</span><span class="s">&#39;4fedffca37eaf&#39;</span><span class="p">,</span>
        <span class="s">&#39;x&#39;</span><span class="p">:</span><span class="mi">27</span><span class="p">,</span>
        <span class="s">&#39;y&#39;</span><span class="p">:</span><span class="mi">450</span>
    <span class="p">}</span>

    <span class="n">old_config</span> <span class="o">=</span> <span class="n">sess</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">ConfigData</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">version_one</span><span class="p">)</span>
    <span class="k">assert</span> <span class="n">old_config</span><span class="o">.</span><span class="n">data</span> <span class="o">==</span> <span class="p">{</span>
        <span class="s">&#39;user_name&#39;</span><span class="p">:</span><span class="s">&#39;twitter&#39;</span><span class="p">,</span>
        <span class="s">&#39;hash_id&#39;</span><span class="p">:</span><span class="s">&#39;4fedffca37eaf&#39;</span><span class="p">,</span>
        <span class="s">&#39;x&#39;</span><span class="p">:</span><span class="mi">27</span><span class="p">,</span>
        <span class="s">&#39;y&#39;</span><span class="p">:</span><span class="mi">450</span>
    <span class="p">}</span>

    <span class="c"># the history of any key can be acquired using</span>
    <span class="c"># the originating_config_id attribute</span>
    <span class="n">history</span> <span class="o">=</span> <span class="n">sess</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">ConfigValue</span><span class="p">)</span><span class="o">.</span>\
            <span class="nb">filter</span><span class="p">(</span><span class="n">ConfigValue</span><span class="o">.</span><span class="n">name</span><span class="o">==</span><span class="s">&#39;user_name&#39;</span><span class="p">)</span><span class="o">.</span>\
            <span class="n">order_by</span><span class="p">(</span><span class="n">ConfigValue</span><span class="o">.</span><span class="n">originating_config_id</span><span class="p">)</span><span class="o">.</span>\
            <span class="nb">all</span><span class="p">()</span>

    <span class="k">assert</span> <span class="p">[(</span><span class="n">h</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">h</span><span class="o">.</span><span class="n">originating_config_id</span><span class="p">)</span> <span class="k">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">history</span><span class="p">]</span> <span class="o">==</span> \
            <span class="p">[(</span><span class="s">&#39;twitter&#39;</span><span class="p">,</span> <span class="n">version_one</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;yahoo&#39;</span><span class="p">,</span> <span class="n">version_two</span><span class="p">)]</span></pre></div>
    </div>

</div>

<div id="docs-bottom-navigation" class="docs-navigation-links">

    <div id="docs-copyright">
        &copy; <a href="../../../copyright.html">Copyright</a> 2007-2014, the SQLAlchemy authors and contributors.
        Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.2b1.
    </div>
</div>

</div>

        
    </body>
</html>