File tree Expand file tree Collapse file tree 3 files changed +96
-6
lines changed Expand file tree Collapse file tree 3 files changed +96
-6
lines changed Original file line number Diff line number Diff line change @@ -102,6 +102,57 @@ def test_reduce_empty(self):
102
102
self .assertEqual (output .getvalue (),
103
103
b'[true, [0]]\n ' )
104
104
105
+ def test_update (self ):
106
+ import json
107
+ commands = [
108
+ [
109
+ 'ddoc' ,
110
+ 'new' ,
111
+ '_design/test_update' ,
112
+ {
113
+ '_id' : '_design/test_update' ,
114
+ '_rev' : '8-d7379de23a751dc2a19e5638a7bbc5cc' ,
115
+ 'language' : 'python' ,
116
+ 'updates' : {
117
+ 'inc' : {
118
+ 'map' : '''\
119
+ def fun(obj, req):
120
+ if obj is not None:
121
+ obj['field'] += 1
122
+ return [obj, {"body": "."}]
123
+ ''' ,
124
+ }
125
+ }
126
+ },
127
+ ],
128
+ [
129
+ 'ddoc' ,
130
+ '_design/test_update' ,
131
+ ['updates' , 'inc' ],
132
+ [None , {}]
133
+ ],
134
+ [
135
+ 'ddoc' ,
136
+ '_design/test_update' ,
137
+ ['updates' , 'inc' ],
138
+ [{'field' : 41 , 'other_field' : 'x' }, {}]
139
+ ],
140
+ ]
141
+ input = StringIO (b'\n ' .join (json .dumps (c ).encode ('utf-8' )
142
+ for c in commands ))
143
+ output = StringIO ()
144
+ view .run (input = input , output = output )
145
+ results = [
146
+ json .loads (l .decode ('utf-8' ))
147
+ for l in output .getvalue ().strip ().split (b'\n ' )
148
+ ]
149
+ self .assertEqual (len (results ), 3 )
150
+ self .assertEqual (results [0 ], True )
151
+ self .assertEqual (results [1 ], ['up' , None , {'body' : '.' }])
152
+ self .assertEqual (
153
+ results [2 ],
154
+ ['up' , {'field' : 42 , 'other_field' : 'x' }, {'body' : '.' }])
155
+
105
156
106
157
def suite ():
107
158
suite = unittest .TestSuite ()
Original file line number Diff line number Diff line change 23
23
24
24
log = logging .getLogger ('couchdb.view' )
25
25
26
+ ddocs = {}
26
27
27
28
def run (input = sys .stdin , output = sys .stdout ):
28
29
r"""CouchDB view function handler implementation for Python.
@@ -135,8 +136,33 @@ def rereduce(*cmd):
135
136
# Note: weird kwargs is for Python 2.5 compat
136
137
return reduce (* cmd , ** {'rereduce' : True })
137
138
138
- handlers = {'reset' : reset , 'add_fun' : add_fun , 'map_doc' : map_doc ,
139
- 'reduce' : reduce , 'rereduce' : rereduce }
139
+ def ddoc (* cmd ):
140
+ if cmd [0 ] == 'new' :
141
+ ddoc = cmd [2 ]
142
+ ddoc ['updates' ] = dict (
143
+ (name , {'map' : compile_fun (value ['map' ])})
144
+ for name , value in ddoc ['updates' ].items ())
145
+ ddocs [cmd [1 ]] = ddoc
146
+ return True
147
+ else :
148
+ ddoc = ddocs [cmd [0 ]]
149
+ action = cmd [1 ]
150
+ if action [0 ] == 'updates' :
151
+ fun = ddoc ['updates' ][action [1 ]]['map' ]
152
+ doc , body = fun (* cmd [2 ])
153
+ res = ['up' , doc , body ]
154
+ sys .stderr .flush ()
155
+ return res
156
+
157
+
158
+ handlers = {
159
+ 'add_fun' : add_fun ,
160
+ 'ddoc' : ddoc ,
161
+ 'map_doc' : map_doc ,
162
+ 'reduce' : reduce ,
163
+ 'rereduce' : rereduce ,
164
+ 'reset' : reset ,
165
+ }
140
166
141
167
try :
142
168
while True :
Original file line number Diff line number Diff line change 1
1
Writing views in Python
2
2
=======================
3
3
4
- The couchdb-python package comes with a view server to allow you to write
5
- views in Python instead of JavaScript. When couchdb-python is installed, it
6
- will install a script called couchpy that runs the view server. To enable
7
- this for your CouchDB server, add the following section to local.ini::
4
+ The couchdb-python package comes with a query server to allow you to
5
+ write views or update handlers in Python instead of JavaScript. When
6
+ couchdb-python is installed, it will install a script called couchpy
7
+ that runs the view server. To enable this for your CouchDB server, add
8
+ the following section to local.ini::
8
9
9
10
[query_servers]
10
11
python=/usr/bin/couchpy
@@ -18,3 +19,15 @@ the language pull-down menu. Here's some sample view code to get you started::
18
19
19
20
Note that the ``map `` function uses the Python ``yield `` keyword to emit
20
21
values, where JavaScript views use an ``emit() `` function.
22
+
23
+ Here's an example update handler code that will increment the
24
+ ``field `` member of an existing document. The name of the ``field `` to
25
+ increment is passed in the query string::
26
+
27
+ def fun(obj, req):
28
+ field = req.query['field']
29
+ if obj is not None and field in obj:
30
+ obj[field] += 1
31
+ return [obj, {"body": "incremented"}]
32
+ else:
33
+ return [None, {"body": "no such document or field"}]
You can’t perform that action at this time.
0 commit comments