Merge lp:~thisfred/desktopcouch/i_believe_you_have_my_couchdb into lp:desktopcouch

Proposed by Eric Casteleijn
Status: Merged
Merged at revision: not available
Proposed branch: lp:~thisfred/desktopcouch/i_believe_you_have_my_couchdb
Merge into: lp:desktopcouch
Diff against target: None lines
To merge this branch: bzr merge lp:~thisfred/desktopcouch/i_believe_you_have_my_couchdb
Reviewer Review Type Date Requested Status
Ubuntu One hackers Pending
Review via email: mp+10560@code.launchpad.net

Commit message

Makes the tests no longer use the user's desktopcouch couchdb.

To post a comment you must log in.
Revision history for this message
Eric Casteleijn (thisfred) wrote :

No longer uses the user's desktopcouch couchdb, which was super ungood. Now creating everything in /tmp and running against that. And leaving it around, and running after the tests... which is only normal ungood. Any pointers on how to execute some code (to stop couch and remove the tempdir) after all the tests have run (or even at the end of each testcase) welcome. I believe Zope testcases have support for this, but my brain is fried for the week.

This has the branch lp:~rick-rickspencer3/desktopcouch/CouchWidget-tests-and-robustness merged in, and any conflicts removed.

47. By Eric Casteleijn

one forgotten checkin

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'desktopcouch/__init__.py'
2--- desktopcouch/__init__.py 2009-08-19 16:00:01 +0000
3+++ desktopcouch/__init__.py 2009-08-21 21:57:37 +0000
4@@ -16,7 +16,7 @@
5 "Desktop Couch helper files"
6
7 from __future__ import with_statement
8-import os, re, errno, time, fcntl
9+import os, re, time
10
11
12 def find_pid(start_if_not_running=True):
13@@ -88,7 +88,7 @@
14 # which was shorter but less reliable)
15
16 proc_dir = "/proc/%s" % (pid,)
17-
18+
19 # enumerate the process' file descriptors
20 fd_dir = os.path.join(proc_dir, 'fd')
21 try:
22@@ -96,7 +96,7 @@
23 for fd in os.listdir(fd_dir)]
24 except OSError:
25 raise RuntimeError("Unable to find file descriptors in /proc")
26-
27+
28
29 # identify socket fds
30 socket_matches = [re.match('socket:\\[([0-9]+)\\]', p) for p in fd_paths]
31@@ -140,11 +140,11 @@
32 os_name = platform.system()
33 try:
34 process_is_couchdb = {
35- "Linux":process_is_couchdb__linux
36+ "Linux": process_is_couchdb__linux
37 } [os_name]
38
39 find_port = {
40- "Linux":find_port__linux
41+ "Linux": find_port__linux
42 } [os_name]
43 except KeyError:
44 raise NotImplementedError("os %r is not yet supported" % (os_name,))
45
46=== modified file 'desktopcouch/contacts/contactspicker.py'
47--- desktopcouch/contacts/contactspicker.py 2009-08-18 23:00:26 +0000
48+++ desktopcouch/contacts/contactspicker.py 2009-08-20 22:14:02 +0000
49@@ -28,18 +28,13 @@
50 class ContactsPicker(gtk.VBox):
51 __gtype_name__ = "ContactsPicker"
52
53- def __init__(self, server_ip = 'http://127.0.0.1:5984/'):
54+ def __init__(self):
55 """Create a new ContactsPicker widget
56- optional arguments:
57- server_ip - specify and ip and port for the server location.
58- Defaults to http://127.0.0.1:5984
59
60 """
61
62 gtk.VBox.__init__(self)
63
64- self.server_ip = server_ip
65-
66 # Create search entry and button
67 hbox = gtk.HBox()
68 self.pack_start(hbox, False, False, 3)
69@@ -51,11 +46,17 @@
70 hbox.pack_start(self.search_button, False, False, 3)
71
72 # Create CouchWidget to contain list of contacts
73- self.contacts_list = CouchWidget(self.server_ip)
74- self.contacts_list.database = 'contacts'
75+ self.contacts_list = CouchWidget('contacts')
76 self.contacts_list.editable = False
77 self.contacts_list.headings = [ "first_name", "last_name" ]
78 self.contacts_list.record_type = CONTACT_RECORD_TYPE
79+
80+ #Pimp out the columns with some nicer titles
81+ #TODO: this should be set up for translatability
82+ columns = self.contacts_list.get_columns()
83+ columns[0].set_title("First Name")
84+ columns[1].set_title("Last Name")
85+
86 self.contacts_list.show()
87 self.pack_start(self.contacts_list, True, True, 3)
88
89
90=== modified file 'desktopcouch/local_files.py'
91--- desktopcouch/local_files.py 2009-08-05 11:18:46 +0000
92+++ desktopcouch/local_files.py 2009-08-21 22:45:24 +0000
93@@ -16,6 +16,8 @@
94 # along with desktopcouch. If not, see <http://www.gnu.org/licenses/>.
95 #
96 # Author: Stuart Langridge <stuart.langridge@canonical.com>
97+# Eric Casteleijn <eric.casteleijn@canonical.com>
98+
99 """Specify location of files relevant to desktop CouchDB.
100
101 Checks to see whether we're running out of the source tree or not.
102@@ -30,48 +32,18 @@
103 "Remove .. from paths"
104 return os.path.realpath(os.path.join(rootdir, path))
105
106-def u1_is_in_source_tree():
107- """If the parent dir of the module directory is "lib", and there is
108- a "tmp" dir and a "README" file, then the u1 code is in a source tree."""
109- try:
110- import ubuntuone
111- except ImportError:
112- return False
113- u1mod_dir, u1mod_file = os.path.split(ubuntuone.__file__)
114- if u1mod_dir.split(os.sep)[-2] != "lib":
115- return False
116-
117- proj_root = os.path.join(u1mod_dir, os.pardir, os.pardir)
118- if not os.path.isdir(os.path.join(proj_root, "tmp")):
119- return False
120-
121- if not os.path.isfile(os.path.join(proj_root, "README")):
122- return False
123-
124- return True
125-
126-
127-if u1_is_in_source_tree():
128- import ubuntuone
129- rootdir = os.path.join(os.path.split(ubuntuone.__file__)[0], "..", "..", "tmp")
130- FILE_INI = mkpath(rootdir, "desktop-couchdb.ini")
131- DIR_DB = mkpath(rootdir, "desktop-couch-files")
132- if not os.path.isdir(DIR_DB):
133- os.makedirs(DIR_DB)
134-else:
135- rootdir = os.path.join(xdg.BaseDirectory.xdg_cache_home, "desktop-couch")
136- if not os.path.isdir(rootdir):
137- os.makedirs(rootdir)
138- config_dir = xdg.BaseDirectory.save_config_path("desktop-couch")
139- FILE_INI = os.path.join(config_dir, "desktop-couchdb.ini")
140- DIR_DB = xdg.BaseDirectory.save_data_path("desktop-couch")
141-
142+rootdir = os.path.join(xdg.BaseDirectory.xdg_cache_home, "desktop-couch")
143+if not os.path.isdir(rootdir):
144+ os.mkdir(rootdir)
145+config_dir = xdg.BaseDirectory.save_config_path("desktop-couch")
146+FILE_INI = os.path.join(config_dir, "desktop-couchdb.ini")
147+DIR_DB = xdg.BaseDirectory.save_data_path("desktop-couch")
148+
149 FILE_PID = mkpath(rootdir, "desktop-couchdb.pid")
150 FILE_LOG = mkpath(rootdir, "desktop-couchdb.log")
151 FILE_STDOUT = mkpath(rootdir, "desktop-couchdb.stdout")
152 FILE_STDERR = mkpath(rootdir, "desktop-couchdb.stderr")
153
154-
155 COUCH_EXE = os.environ.get('COUCHDB')
156 if not COUCH_EXE:
157 for x in os.environ['PATH'].split(':'):
158@@ -92,7 +64,6 @@
159
160 return chain
161
162-
163 # You will need to add -b or -k on the end of this
164 COUCH_EXEC_COMMAND = [COUCH_EXE, couch_chain_flag(), FILE_INI, '-p', FILE_PID,
165 '-o', FILE_STDOUT, '-e', FILE_STDERR]
166
167=== modified file 'desktopcouch/pair/tests/test_network_io.py'
168--- desktopcouch/pair/tests/test_network_io.py 2009-07-10 22:13:01 +0000
169+++ desktopcouch/pair/tests/test_network_io.py 2009-08-21 21:57:37 +0000
170@@ -17,21 +17,14 @@
171
172 import pygtk
173 pygtk.require('2.0')
174-import gtk
175
176 from twisted.internet import gtk2reactor
177 gtk2reactor.install()
178 from twisted.internet import reactor, task
179
180-
181-if __name__ == "__main__":
182- import sys, os
183- sys.path.append(os.pardir)
184- from couchdb_pairing.network_io import start_send_invitation, ListenForInvitations
185- from couchdb_pairing.dbus_io import get_local_hostname
186-else:
187- from ..couchdb_pairing.network_io import start_send_invitation, ListenForInvitations
188- from ..couchdb_pairing.dbus_io import get_local_hostname
189+from desktopcouch.pair.couchdb_pairing.network_io import (
190+ start_send_invitation, ListenForInvitations)
191+from desktopcouch.pair.couchdb_pairing.dbus_io import get_local_hostname
192
193 import unittest
194
195@@ -49,7 +42,7 @@
196 def test_successful_lifespan(self):
197
198 secret = "sekrit"
199-
200+
201 def listener_get_secret_from_user(sender, f, send_secret):
202 """Get secret from user. Try several first."""
203 self.assertFalse(f("sek"))
204@@ -106,7 +99,7 @@
205 def disabled__test_inviter_quits(self):
206
207 secret = "sekrit"
208-
209+
210 def listener_get_secret_from_user(sender, f, send_secret):
211 """Get secret from user. Try several first."""
212 self.assertFalse(f("sek"))
213@@ -152,7 +145,7 @@
214 def disabled__test_listener_quits(self):
215
216 secret = "sekrit"
217-
218+
219 def listener_get_secret_from_user(sender, f, send_secret):
220 """Get secret from user. Try several first."""
221 self.assertFalse(f("sek"))
222@@ -193,9 +186,3 @@
223
224 self.assertEqual(self._listener_socket_state, "closed")
225 self.assertEqual(self._inviter_socket_state, "closed")
226-
227-
228-if __name__ == "__main__":
229- import logging
230- logging.basicConfig(level=logging.ERROR)
231- unittest.main()
232
233=== modified file 'desktopcouch/records/couchwidget.py'
234--- desktopcouch/records/couchwidget.py 2009-08-19 23:01:09 +0000
235+++ desktopcouch/records/couchwidget.py 2009-08-21 23:46:57 +0000
236@@ -26,24 +26,48 @@
237 class CouchWidget(gtk.TreeView):
238 __gtype_name__ = "CouchWidget"
239
240- def __init__(self, server_ip = 'http://127.0.0.1:5984/'):
241+ def __init__(
242+ self, database_name, record_type=None, headings=None, uri=None):
243 """Create a new Couchwidget
244+ arguments:
245+ database_name - specify the name of the database in the desktop
246+ couchdb to use. If the specified database does not exist, it
247+ will be created.
248+
249 optional arguments:
250- server_ip - specify and ip and port for the server location.
251- Defaults to http://127.0.0.1:5984
252-
253+ record_type - a string to specify the record_type to use in
254+ retrieving and creating records. Note that if no records are
255+ set the headings argument must also be used or a RuntimeError
256+ will result.
257+
258+ headings - a list of strings specifying headings to use in
259+ the columns of the CouchWidget.
260+
261+ Note that the CouchWidget uses headings for keys, and visa versa.
262+ If a record does not contain a value for a specified value
263+ the CouchWidget will simply display an empty string for the
264+ value. If the widget is set to editable, the user will be able
265+ to add values to the database.
266+
267 """
268
269 gtk.TreeView.__init__(self)
270
271- #assume a local server
272- self.server_ip = server_ip
273-
274 #set up the default values
275- self.__db = None
276+ if type(database_name) is not type(str()):
277+ raise TypeError("database_name is required and must be a string")
278+
279+ #set up default values
280 self.__record_type = None
281- self.__headings = None
282+ self.__headings = headings
283 self.__editable = False
284+ self.uri = uri
285+
286+ #set the datatabase
287+ self.database = database_name
288+ if record_type is not None:
289+ self.record_type = record_type
290+
291 self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
292
293 @property
294@@ -57,7 +81,7 @@
295 value. If the widget is set to editable, the user will be able
296 to add values to the database.
297
298- Setting this property will cause the widget to reload.
299+ Setting this property will cause the widget to reload.
300
301 """
302
303@@ -84,20 +108,22 @@
304
305 #refresh the treeview if possible
306 if self.record_type != None:
307- self.__populate_treeview()(self.record_type)
308+ self.__populate_treeview()
309
310 @property
311 def database(self):
312 """database - gets an instance to the CouchDB.
313 Set to a string to change the database.
314
315- """
316+ """
317 return self.__db
318
319 @database.setter
320 def database(self, db_name):
321- self.__db = CouchDatabase(db_name, uri=self.server_ip, create=True)
322-
323+ if self.uri:
324+ self.__db = CouchDatabase(db_name, create=True, uri=self.uri)
325+ else:
326+ self.__db = CouchDatabase(db_name, create=True)
327 if self.record_type != None:
328 self.__populate_treeview()(self.record_type)
329
330@@ -119,30 +145,52 @@
331
332 def __populate_treeview(self):
333 #if the database is not set up, just return
334- if self.__db == None or self.__headings == None:
335+ if self.__db == None:
336 return
337
338- #refresh the model structure
339- self.__reset_model()
340+ #the cases with headings are complex and hacky
341+ #there are the following cases:
342+ #1. headings have not been set and cannot be inferred
343+ #2. headings have been previously set
344+ #3. headings should be inferred from results
345+
346
347 #retrieve the docs for the record_type, if any
348- results = self.__db.get_records(record_type=self.__record_type,create_view=True)
349+ results = self.__db.get_records(
350+ record_type=self.__record_type,create_view=True)
351+
352+ #test for headings case 1 and raise an exception
353+ if len(results) < 1 and self.headings == None:
354+ raise RuntimeError("""Cannot infer columns for CouchWidget.
355+ Ensure that records exist, or define columns using
356+ CouchWidget.headings property.
357+ """)
358+
359+ #test for case 2, and set up the model
360+ if self.headings is not None:
361+ self.__reset_model()
362
363 #if headings are already assigned, set up headings and columns
364+ #for headings case 2 with or without results
365 if self.headings != None:
366 self.__make_headings()
367
368 first_row = True
369 for r in results:
370- #if headings are not set up, infer them from
371- #the first stored record
372+ #handle headings case 3
373+ #if headings are not set up, infer them from
374 if self.headings == None and first_row:
375 self.headings = []
376 for k in r.value.keys():
377 if not k.startswith("_") and k != "record_type":
378 self.headings.append(k)
379 #now set up the columns and headers
380- self.__make_headings()
381+ self.__make_headings()
382+
383+ #in headings case 3 the model has not been set yet
384+ #so do that now
385+ self.__reset_model()
386+
387 first_row = False
388
389 #lists have to match the list_store columns in length
390@@ -152,19 +200,19 @@
391 row = ["" for i in xrange(col_count)]
392
393 #replace the values in the row with the values in the
394- #retrieved rows. If the the key is not in the doc,
395+ #retrieved rows. If the the key is not in the doc,
396 #just continue with an empty string
397 for i, h in enumerate(self.headings):
398 try:
399 row[i] = r.value[h]
400 except:
401 pass
402-
403+
404 #set the last value as the document_id, and append
405 row[-1] = r.key
406 self.list_store.append(row)
407
408- #apply the model tot he Treeview
409+ #apply the model tot he Treeview
410 self.set_model(self.list_store)
411
412 def append_row(self, new_row, auto_save = True):
413@@ -176,45 +224,48 @@
414 to specify all values to include in the new row, as
415 append_row will copy all the values starting at position 0
416 and will fill in the remaining values with empty strings.
417-
418+
419 auto_save - if True will immediately commit the row
420 to the database. Otherwise, the row won't be saved until
421 a cell is edited. Typically should be False if adding an
422- empty row. An empty list will not be autosaved, even if
423+ empty row. An empty list will not be autosaved, even if
424 auto_save is set to True.
425
426 Defaults to True.
427
428 """
429
430+ #TODO: add gaurd conditions
431+ #throw if no database is set
432+
433 #lists have to match the list_store columns in length
434 #note that the last value is reserved for the doc_id
435 col_count = len(self.headings) + 1
436 row = ["" for i in xrange(col_count)]
437-
438+
439 #create a document for autosaving
440- doc = {"record_type":self.record_type}
441-
442+ doc = {"record_type":self.record_type}
443+
444 #copy the values into the row
445 #add to the document in case it needs to be auto saved
446 for i, v in enumerate(new_row):
447 row[i] = new_row[i]
448 doc[self.headings[i]] = new_row[i]
449-
450+
451 rec = Record(doc)
452
453 #auto save non-empty rows
454 if auto_save and len(new_row) > 0:
455 doc_id = self.__db.put_record(rec)
456 row[len(self.headings)] = doc_id #store the id
457-
458+
459 #add it to the list store
460 self.list_store.append(row)
461
462 @property
463 def selected_rows(self):
464- """ selected_rows - returns a list of dictionaries
465- for each row selected. Note that the values are not
466+ """ selected_rows - returns a list of dictionaries
467+ for each row selected. Note that the values are not
468 necessarily the complete dictionary for the records, but rather
469 are determined by the headings used for the CouchWidget.
470
471@@ -236,7 +287,7 @@
472 #get the value for each heading and add it to the row
473 for i, h in enumerate(self.headings):
474 row[h] = model.get_value(iter,i)
475-
476+
477 #add the row to the list
478 rows.append(row)
479 return rows
480@@ -244,7 +295,7 @@
481 @property
482 def selected_record_ids(self):
483 """ selected_record_ids - a list of document ids that are
484- selected in the CouchWidget. Throws an IndexError if
485+ selected in the CouchWidget. Throws an IndexError if
486 a specified id is not found in the list when setting
487 this property.
488
489@@ -269,7 +320,7 @@
490 @selected_record_ids.setter
491 def selected_record_ids(self, indexes):
492 rows = [] #a list of rows to select
493- for id in indexes:
494+ for id in indexes:
495 id_found = False #track if the id was found
496
497 for i,r in enumerate(self.list_store):
498@@ -286,7 +337,7 @@
499 selection.unselect_all()
500 for r in rows:
501 selection.select_path(r)
502-
503+
504 @property
505 def selected_records(self):
506 """ selected_records - returns a list of Record objects
507@@ -296,7 +347,7 @@
508
509 """
510 recs = [] #a list of records to return
511- for id in self.selected_record_ids:
512+ for id in self.selected_record_ids:
513 #retrieve a record for each id
514 recs.append(Record(record_id = id, record_type = self.record_type))
515 return recs
516@@ -314,12 +365,12 @@
517
518 #make a new ListStore
519 col_count = len(self.headings) + 1
520- self.list_store = gtk.ListStore(*[gobject.TYPE_STRING for i in xrange(col_count)])
521-
522+ self.list_store = gtk.ListStore(
523+ *[gobject.TYPE_STRING for i in xrange(col_count)])
524
525 def __make_headings(self):
526 """ __make_headings - internal funciton do not call direclty
527- Sets up the headings and columnss for the TreeView.
528+ Sets up the headings and columns for the TreeView.
529
530 """
531
532@@ -334,12 +385,12 @@
533 #create a column and add to the TreeView
534 col = gtk.TreeViewColumn(h, rend, text=i)
535 self.append_column(col)
536-
537+
538 def __edited(self, cellrenderertext, path, new_text, col):
539 """ __edited - internal signal handler.
540 Updates the database if a cell in the Treeview
541 has been edited.
542-
543+
544 """
545
546 #get an iterator that points to the edited row
547@@ -356,10 +407,10 @@
548 if id == "": #the row has not been stored
549 #create a document
550 doc = {"record_type":self.record_type}
551-
552+
553 for i, h in enumerate(self.headings):
554 #copy the all the values into the doc
555- doc[h] = self.list_store.get_value(iter,i)
556+ doc[h] = self.list_store.get_value(iter,i)
557
558 rec = Record(doc)
559 #save the document and store the id
560@@ -383,7 +434,7 @@
561 disp += "\n\nRecords:\n"
562 for r in cw.selected_records:
563 disp += str(r) + "\n"
564-
565+
566 tv.get_buffer().set_text(disp)
567
568 def __select_ids(widget, widgets):
569@@ -391,7 +442,7 @@
570 try:
571 cw.selected_record_ids = entry.get_text().split(",")
572 except Exception, inst:
573- lbl.set_text(str(inst))
574+ lbl.set_text(str(inst))
575
576 if __name__ == "__main__":
577 """creates a test CouchWidget if called directly"""
578@@ -408,19 +459,12 @@
579 win.add(vbox)
580
581 #create a test widget with test database values
582- cw = CouchWidget()
583- cw.database = "couch_widget_test"
584+ cw = CouchWidget("couch_widget_test", record_type="test_record_type",
585+ headings=["Key1", "Key2", "Key3", "Key4"])
586
587 #allow editing
588 cw.editable = True
589
590- #create headers/keys
591- cw.headings = ["Key1","Key2","Key3","Key4"]
592-
593- #set the record_type for the TreeView
594- #it will not populate without this value being set
595- cw.record_type = "test_record_type"
596-
597 #create a row with all four columns set
598 cw.append_row(["val1","val2","val3","val4"])
599
600@@ -442,12 +486,10 @@
601 tv.show()
602 cw.connect("cursor-changed",__show_selected, (tv,cw))
603
604-
605 #create ui for testing selection
606 id_vbox = gtk.VBox(False, 5)
607 id_vbox.show()
608
609-
610 fb_lbl = gtk.Label("paste ids into the edit box to select them")
611 fb_lbl.show()
612
613
614=== modified file 'desktopcouch/records/server.py'
615--- desktopcouch/records/server.py 2009-08-10 21:32:52 +0000
616+++ desktopcouch/records/server.py 2009-08-21 22:45:24 +0000
617@@ -21,7 +21,6 @@
618
619 """The Desktop Couch Records API."""
620
621-import urllib
622 from couchdb import Server
623 from couchdb.client import ResourceNotFound, ResourceConflict
624 from couchdb.design import ViewDefinition
625@@ -155,7 +154,7 @@
626
627 # sync_many does nothing if we pass an empty list. It even gets
628 # its design-document from the ViewDefinition items, and if there
629- # are no items, then it has no idea of a design document to
630+ # are no items, then it has no idea of a design document to
631 # update. This is a serious flaw. Thus, the "else" to follow.
632 ViewDefinition.sync_many(self.db, views, remove_missing=True)
633 else:
634@@ -219,16 +218,16 @@
635 special value, None, is analogous to O_EXCL|O_CREAT .
636
637 Set record_type to a string to retrieve records of only that
638- specified type. Otherwise, usse the view to return *all* records.
639- If there is no view to use or we insist on creating a new view
640+ specified type. Otherwise, usse the view to return *all* records.
641+ If there is no view to use or we insist on creating a new view
642 and cannot, raise KeyError .
643
644- You can use index notation on the result to get rows with a
645+ You can use index notation on the result to get rows with a
646 particular record type.
647 =>> results = get_records()
648 =>> for foo_document in results["foo"]:
649 ... print foo_document
650-
651+
652 Use slice notation to apply start-key and end-key options to the view.
653 =>> results = get_records()
654 =>> people = results[['Person']:['Person','ZZZZ']]
655@@ -250,7 +249,7 @@
656
657 if not exists:
658 self.add_view(view_name, view_map_js, None, design_doc)
659-
660+
661 viewdata = self.execute_view(view_name, design_doc)
662 if record_type is None:
663 return viewdata
664
665=== modified file 'desktopcouch/records/tests/__init__.py'
666--- desktopcouch/records/tests/__init__.py 2009-07-08 17:48:11 +0000
667+++ desktopcouch/records/tests/__init__.py 2009-08-21 22:47:25 +0000
668@@ -14,3 +14,27 @@
669 # You should have received a copy of the GNU Lesser General Public License
670 # along with desktopcouch. If not, see <http://www.gnu.org/licenses/>.
671 """Tests for Documents API"""
672+
673+import os, tempfile
674+from desktopcouch.local_files import COUCH_EXE, couch_chain_flag
675+from desktopcouch.start_local_couchdb import create_ini_file, run_couchdb
676+
677+directory = tempfile.mkdtemp()
678+ini_path = os.path.join(directory, "test_couchdb.ini")
679+log_path = os.path.join(directory, "test_couchdb.log")
680+pid_path = os.path.join(directory, "test_couchdb.pid")
681+stdout_path = os.path.join(directory, "test_couchdb.stdout")
682+stderr_path = os.path.join(directory, "test_couchdb.stderr")
683+
684+db_dir = os.path.join(directory, "test_couchdb")
685+os.mkdir(db_dir)
686+
687+port = "21224"
688+create_ini_file(
689+ ini_path=ini_path, db_dir=db_dir, log_path=log_path, port=port)
690+exec_command = [
691+ COUCH_EXE, couch_chain_flag(), ini_path, '-p', pid_path, '-o', stdout_path,
692+ '-e', stderr_path]
693+exec_command[2] = ini_path
694+run_couchdb(exec_command=exec_command)
695+URI = "htpp://localhost:%s" % port
696
697=== modified file 'desktopcouch/records/tests/test_couchwidget.py'
698--- desktopcouch/records/tests/test_couchwidget.py 2009-08-19 23:01:09 +0000
699+++ desktopcouch/records/tests/test_couchwidget.py 2009-08-21 23:46:57 +0000
700@@ -19,76 +19,182 @@
701 """Tests for the couchwidget object"""
702
703 from testtools import TestCase
704+from desktopcouch.records.record import Record
705 from desktopcouch.records.server import CouchDatabase
706 from desktopcouch.records.couchwidget import CouchWidget
707+from desktopcouch.records.tests import URI
708+
709
710 class TestCouchWidget(TestCase):
711 """Test the CouchWidget functionality"""
712+
713 def setUp(self):
714- self.dbname = "couch_widget_test"
715+ self.dbname = self._testMethodName
716+ self.db = CouchDatabase(self.dbname, create=True, uri=URI)
717 self.record_type = "test_record_type"
718
719- def test_headings_first(self):
720- #create a test widget with test database values
721- cw = CouchWidget()
722- cw.database = self.dbname
723-
724- #allow editing
725- cw.editable = True
726-
727- #create headers/keys
728- cw.headings = ["Key1","Key2","Key3","Key4"]
729-
730- #set the record_type for the TreeView
731- #it will not populate without this value being set
732- cw.record_type = self.record_type
733-
734- #create a row with all four columns set
735- cw.append_row(["val1","val2","val3","val4"])
736-
737- #create a row with only the second column set
738- cw.append_row(["","val2"])
739-
740- #create an empty row (which will not be saved until the user edits it)
741- cw.append_row([])
742-
743- self.assertEqual(cw.record_type, self.record_type)
744- self.__delete_db()
745-
746- def test_record_type_first(self):
747- #create a test widget with test database values
748- cw = CouchWidget()
749- cw.database = self.dbname
750-
751- #allow editing
752- cw.editable = True
753-
754- #set the record_type for the TreeView
755- #it will not populate without this value being set
756- cw.record_type = self.record_type
757-
758- #create headers/keys
759- cw.headings = ["Key1","Key2","Key3","Key4"]
760-
761- #create a row with all four columns set
762- cw.append_row(["val1","val2","val3","val4"])
763-
764- #create a row with only the second column set
765- cw.append_row(["","val2"])
766-
767- #create an empty row (which will not be saved until the user edits it)
768- cw.append_row([])
769-
770- self.assertEqual(cw.record_type, self.record_type)
771- self.__delete_db()
772-
773 def tearDown(self):
774 """tear down each test"""
775- self.__delete_db()
776 #delete the database
777-
778- def __delete_db(self):
779- db = CouchDatabase(self.dbname, create=True)
780- del db._server[self.dbname]
781-
782-
783+ del self.db._server[self.dbname]
784+
785+ def test_constructor_guarded(self):
786+ """Ensure that couchwidget cannot be constructed without a
787+ database name.
788+ """
789+ try:
790+ cw = CouchWidget(None, uri=URI)
791+ except TypeError, inst:
792+ self.assertEqual(
793+ inst.args[0],"database_name is required and must be a string")
794+
795+ def test_new_rows_with_headings(self):
796+ """Test a simple creating a couchwidget """
797+
798+ #create a test widget with test database values
799+ cw = CouchWidget(self.dbname, uri=URI)
800+
801+ #allow editing
802+ cw.editable = True
803+
804+ #create headers/keys
805+ cw.headings = ["Key1", "Key2", "Key3", "Key4"]
806+
807+ #set the record_type for the TreeView
808+ #it will not populate without this value being set
809+ cw.record_type = self.record_type
810+
811+ #create a row with all four columns set
812+ cw.append_row(["val1", "val2", "val3", "val4"])
813+
814+ #create a row with only the second column set
815+ cw.append_row(["", "val2"])
816+
817+ #create an empty row (which will not be saved until the user edits it)
818+ cw.append_row([])
819+
820+ #if this all worked, there should be three rows in the model
821+ model = cw.get_model()
822+ self.assertEqual(len(model), 3)
823+
824+ def test_no_headings_or_stored_records(self):
825+ """test when there is no defined headings and no stored records
826+ to infer headings from. Should raise a proper exception.
827+ """
828+
829+ try:
830+ #create a test widget with test database values
831+ cw = CouchWidget(self.dbname, uri=URI)
832+
833+ #set the record_type for the TreeView
834+ #it will not populate without this value being set
835+ cw.record_type = self.record_type
836+
837+ #create a row with all four columns set
838+ cw.append_row(["val1", "val2", "val3", "val4"])
839+
840+ #create a row with only the second column set
841+ cw.append_row(["", "val2"])
842+
843+ #create an empty row (which will not be saved until the
844+ #user edits it)
845+ cw.append_row([])
846+
847+ #if this all worked, there should be three rows in the model
848+ model = cw.get_model()
849+
850+ #should be catching the following exception
851+ except RuntimeError, inst:
852+ self.assertEquals(
853+ inst.args[0].find("Cannot infer columns for CouchWidget"),0)
854+
855+ def test_all_from_database(self):
856+ #create some records
857+ db = CouchDatabase(self.dbname, create=True, uri=URI)
858+ db.put_record(Record({
859+ "key1_1": "val1_1", "key1_2": "val1_2", "key1_3": "val1_3",
860+ "record_type": self.record_type}))
861+ db.put_record(Record({
862+ "key2_1": "val2_1", "key2_2": "val2_2", "key2_3": "val2_3",
863+ "record_type": self.record_type}))
864+
865+ #build the couchwidget
866+ cw = CouchWidget(self.dbname, uri=URI)
867+ cw.record_type = self.record_type
868+ #make sure there are three columns and two rows
869+ self.assertEqual(cw.get_model().get_n_columns(),4)
870+ self.assertEqual(len(cw.get_model()),2)
871+
872+ def test_single_col_from_database(self):
873+ #create some records
874+ self.db.put_record(Record({
875+ "key1_1": "val1_1", "key1_2": "val1_2", "key1_3": "val1_3",
876+ "record_type": self.record_type}))
877+ self.db.put_record(Record({
878+ "key1_1": "val2_1", "key1_2": "val2_2", "key1_3": "val2_3",
879+ "record_type": self.record_type}))
880+ #build the couchwidget
881+ cw = CouchWidget(self.dbname, uri=URI)
882+ cw.headings = ["key1_1"]
883+ cw.record_type = self.record_type
884+ #make sure there are three columns and two rows
885+ self.assertEqual(cw.get_model().get_n_columns(),2)
886+ self.assertEqual(len(cw.get_model()),2)
887+
888+ def test_optional_record_type_arg(self):
889+ """Test a simple creating a couchwidget """
890+ #create some records
891+ self.db.put_record(Record({
892+ "key1_1": "val1_1", "key1_2": "val1_2", "key1_3": "val1_3",
893+ "record_type": self.record_type}))
894+ self.db.put_record(Record({
895+ "key2_1": "val2_1", "key2_2": "val2_2", "key2_3": "val2_3",
896+ "record_type": self.record_type}))
897+
898+ #create a test widget with test database values
899+ cw = CouchWidget(self.dbname, record_type=self.record_type, uri=URI)
900+
901+ #make sure there are three columns and two rows
902+ self.assertEqual(cw.get_model().get_n_columns(),4)
903+ self.assertEqual(len(cw.get_model()),2)
904+
905+ def test_optional_args_no_stored_records(self):
906+ """Test a simple creating a couchwidget """
907+
908+ #create a test widget with test database values
909+ cw = CouchWidget(
910+ self.dbname, record_type=self.record_type,
911+ headings=["Key1", "Key2", "Key3", "Key4"], uri=URI)
912+
913+ #create a row with all four columns set
914+ cw.append_row(["val1", "val2", "val3", "val4"])
915+
916+ #create a row with only the second column set
917+ cw.append_row(["", "val2"])
918+
919+ #create an empty row (which will not be saved until the user edits it)
920+ cw.append_row([])
921+
922+ #if this all worked, there should be three rows in the model
923+ model = cw.get_model()
924+ self.assertEqual(len(model), 3)
925+
926+ def test_programatically_add_row(self):
927+ """test appending different sized rows programatically"""
928+ #create some records
929+ self.db.put_record(Record({
930+ "key1_1": "val1_1", "key1_2": "val1_2", "key1_3": "val1_3",
931+ "record_type": self.record_type}))
932+ self.db.put_record(Record({
933+ "key2_1": "val2_1", "key2_2": "val2_2", "key2_3": "val2_3",
934+ "record_type": self.record_type}))
935+
936+ #create a test widget with test database values
937+ cw = CouchWidget(self.dbname, record_type=self.record_type, uri=URI)
938+
939+ #allow editing
940+ cw.append_row(["boo", "ray"])
941+
942+ #make sure there are three columns and two rows
943+ self.assertEqual(cw.get_model().get_n_columns(),4)
944+ self.assertEqual(len(cw.get_model()),3)
945
946=== modified file 'desktopcouch/records/tests/test_server.py'
947--- desktopcouch/records/tests/test_server.py 2009-08-12 14:26:40 +0000
948+++ desktopcouch/records/tests/test_server.py 2009-08-21 22:45:24 +0000
949@@ -17,12 +17,10 @@
950 # Authors: Eric Casteleijn <eric.casteleijn@canonical.com>
951
952 """testing database/contact.py module"""
953-
954 import testtools
955-import random
956-from desktopcouch.stop_local_couchdb import stop_couchdb
957 from desktopcouch.records.server import CouchDatabase
958 from desktopcouch.records.record import Record
959+from desktopcouch.records.tests import URI
960
961 FAKE_RECORD_TYPE = "http://example.org/test"
962
963@@ -33,33 +31,38 @@
964 }
965 }""" % FAKE_RECORD_TYPE
966
967+
968 class TestCouchDatabase(testtools.TestCase):
969 """tests specific for CouchDatabase"""
970
971+
972 def setUp(self):
973 """setup each test"""
974 # Connect to CouchDB server
975 self.dbname = self._testMethodName
976- self.database = CouchDatabase(self.dbname, create=True)
977-
978+ self.database = CouchDatabase(
979+ self.dbname, create=True, uri=URI)
980 #create some records to pull out and test
981- self.database.put_record(Record({"key1_1":"val1_1","key1_2":"val1_2","key1_3":"val1_3","record_type":"test.com"}))
982- self.database.put_record(Record({"key2_1":"val2_1","key2_2":"val2_2","key2_3":"val2_3","record_type":"test.com"}))
983- self.database.put_record(Record({"key13_1":"va31_1","key3_2":"val3_2","key3_3":"val3_3","record_type":"test.com"}))
984+ self.database.put_record(Record({
985+ "key1_1": "val1_1", "key1_2": "val1_2", "key1_3": "val1_3",
986+ "record_type": "test.com"}))
987+ self.database.put_record(Record({
988+ "key2_1": "val2_1", "key2_2": "val2_2", "key2_3": "val2_3",
989+ "record_type": "test.com"}))
990+ self.database.put_record(Record({
991+ "key13_1": "va31_1", "key3_2": "val3_2", "key3_3": "val3_3",
992+ "record_type": "test.com"}))
993
994 def tearDown(self):
995 """tear down each test"""
996 del self.database._server[self.dbname]
997- if random.choice([1,2,3,4]) == 3: # don't harass it unnecessarily
998- print u"\u2620", # death
999- stop_couchdb()
1000
1001 def test_get_records_by_record_type_save_view(self):
1002 """Test getting mutliple records by type"""
1003- records = self.database.get_records(record_type="test.com",create_view=True)
1004+ records = self.database.get_records(
1005+ record_type="test.com",create_view=True)
1006 self.assertEqual(3,len(records))
1007
1008-
1009 def test_get_record(self):
1010 """Test getting a record."""
1011 record = Record({'record_number': 0}, record_type="http://example.com/")
1012@@ -122,14 +125,18 @@
1013 }"""
1014
1015 # add two and delete two.
1016- self.assertRaises(KeyError, self.database.delete_view, view1_name, design_doc)
1017- self.assertRaises(KeyError, self.database.delete_view, view2_name, design_doc)
1018+ self.assertRaises(
1019+ KeyError, self.database.delete_view, view1_name, design_doc)
1020+ self.assertRaises(
1021+ KeyError, self.database.delete_view, view2_name, design_doc)
1022 self.database.add_view(view1_name, map_js, reduce_js, design_doc)
1023 self.database.add_view(view2_name, map_js, reduce_js, design_doc)
1024 self.database.delete_view(view1_name, design_doc)
1025- self.assertRaises(KeyError, self.database.delete_view, view1_name, design_doc)
1026+ self.assertRaises(
1027+ KeyError, self.database.delete_view, view1_name, design_doc)
1028 self.database.delete_view(view2_name, design_doc)
1029- self.assertRaises(KeyError, self.database.delete_view, view2_name, design_doc)
1030+ self.assertRaises(
1031+ KeyError, self.database.delete_view, view2_name, design_doc)
1032
1033 def test_func_get_records(self):
1034 record_ids_we_care_about = set()
1035
1036=== modified file 'desktopcouch/start_local_couchdb.py'
1037--- desktopcouch/start_local_couchdb.py 2009-08-19 16:00:01 +0000
1038+++ desktopcouch/start_local_couchdb.py 2009-08-21 22:45:24 +0000
1039@@ -16,6 +16,8 @@
1040 # along with desktopcouch. If not, see <http://www.gnu.org/licenses/>.
1041 #
1042 # Author: Stuart Langridge <stuart.langridge@canonical.com>
1043+# Eric Casteleijn <eric.casteleijn@canonical.com>
1044+
1045 """
1046 Start local CouchDB server.
1047 Steps:
1048@@ -54,40 +56,31 @@
1049 fd.write("\n")
1050 fd.close()
1051
1052-def create_ini_file():
1053+def create_ini_file(
1054+ ini_path=local_files.FILE_INI, db_dir=local_files.DIR_DB,
1055+ log_path=local_files.FILE_LOG, port="0"):
1056 """Write CouchDB ini file if not already present"""
1057- # FIXME add update trigger folder
1058- #update_trigger_dir = [
1059- # 'lib', 'canonical', 'ubuntuone', 'cloud_server', 'update_triggers']
1060- #
1061- #timestamp_trigger = os.path.join(
1062- # *update_trigger_dir + ['timestamp_trigger.py'])
1063- #update_trigger = os.path.join(
1064- # *update_trigger_dir + ['update_trigger.py'])
1065-
1066- if os.path.exists(local_files.FILE_INI):
1067+ if os.path.exists(ini_path):
1068 return
1069-
1070- local = {
1071+ ini = {
1072 'couchdb': {
1073- 'database_dir': local_files.DIR_DB,
1074- 'view_index_dir': local_files.DIR_DB,
1075+ 'database_dir': db_dir,
1076+ 'view_index_dir': db_dir,
1077 },
1078 'httpd': {
1079 'bind_address': '127.0.0.1',
1080- 'port': "0",
1081+ 'port': port,
1082 },
1083 'log': {
1084- 'file': local_files.FILE_LOG,
1085+ 'file': log_path,
1086 'level': 'info',
1087 },
1088 }
1089-
1090- dump_ini(local, local_files.FILE_INI)
1091-
1092-def run_couchdb():
1093+ dump_ini(ini, ini_path)
1094+
1095+def run_couchdb(exec_command=local_files.COUCH_EXEC_COMMAND):
1096 """Actually start the CouchDB process"""
1097- local_exec = local_files.COUCH_EXEC_COMMAND + ['-b']
1098+ local_exec = exec_command + ['-b']
1099 try:
1100 # subprocess is buggy. Chad patched, but that takes time to propagate.
1101 proc = subprocess.Popen(local_exec)
1102@@ -109,39 +102,42 @@
1103
1104 def update_design_documents():
1105 """Check system design documents and update any that need updating
1106-
1107- A database should be created if
1108+
1109+ A database should be created if
1110 $XDG_DATA_DIRs/desktop-couch/databases/dbname/database.cfg exists
1111 Design docs are defined by the existence of
1112- $XDG_DATA_DIRs/desktop-couch/databases/dbname/_design/designdocname/views/viewname/map.js
1113+ $XDG_DATA_DIRs/desktop-couch/databases/dbname/_design/designdocname/views/viewname/map.js
1114 reduce.js may also exist in the same folder.
1115 """
1116 for base in xdg.BaseDirectory.xdg_data_dirs:
1117- db_spec = os.path.join(base, "desktop-couch", "databases", "*", "database.cfg")
1118+ db_spec = os.path.join(
1119+ base, "desktop-couch", "databases", "*", "database.cfg")
1120 for database_path in glob.glob(db_spec):
1121 database_root = os.path.split(database_path)[0]
1122 database_name = os.path.split(database_root)[1]
1123 # Just the presence of database.cfg is enough to create the database
1124 db = CouchDatabase(database_name, create=True)
1125 # look for design documents
1126- dd_spec = os.path.join(database_root, "_design", "*", "views", "*", "map.js")
1127+ dd_spec = os.path.join(
1128+ database_root, "_design", "*", "views", "*", "map.js")
1129 for dd_path in glob.glob(dd_spec):
1130 view_root = os.path.split(dd_path)[0]
1131 view_name = os.path.split(view_root)[1]
1132 dd_root = os.path.split(os.path.split(view_root)[0])[0]
1133 dd_name = os.path.split(dd_root)[1]
1134-
1135+
1136 def load_js_file(filename_no_extension):
1137- fn = os.path.join(view_root, "%s.js" % (filename_no_extension))
1138+ fn = os.path.join(
1139+ view_root, "%s.js" % (filename_no_extension))
1140 if not os.path.isfile(fn): return None
1141 fp = open(fn)
1142 data = fp.read()
1143 fp.close()
1144 return data
1145-
1146+
1147 mapjs = load_js_file("map")
1148 reducejs = load_js_file("reduce")
1149-
1150+
1151 # XXX check whether this already exists or not, rather
1152 # than inefficiently just overwriting it regardless
1153 db.add_view(view_name, mapjs, reducejs, dd_name)
1154@@ -150,13 +146,16 @@
1155 """Write out an HTML document that the user can bookmark to find their DB"""
1156 bookmark_file = os.path.join(local_files.DIR_DB, "couchdb.html")
1157
1158- if os.path.exists(os.path.join(os.path.split(__file__)[0], "../data/couchdb.tmpl")):
1159- bookmark_template = os.path.join(os.path.split(__file__)[0], "../data/couchdb.tmpl")
1160+ if os.path.exists(
1161+ os.path.join(os.path.split(__file__)[0], "../data/couchdb.tmpl")):
1162+ bookmark_template = os.path.join(
1163+ os.path.split(__file__)[0], "../data/couchdb.tmpl")
1164 else:
1165 for base in xdg.BaseDirectory.xdg_data_dirs:
1166 template_path = os.path.join(base, "desktopcouch", "couchdb.tmpl")
1167 if os.path.exists(template_path):
1168- bookmark_template = os.path.join(os.path.split(__file__)[0], template_path)
1169+ bookmark_template = os.path.join(
1170+ os.path.split(__file__)[0], template_path)
1171
1172 fp = open(bookmark_template)
1173 html = fp.read()
1174@@ -175,7 +174,8 @@
1175 continue
1176
1177 if port is None:
1178- print "We couldn't find desktop-CouchDB's network port. Bookmark file not written."
1179+ print ("We couldn't find desktop-CouchDB's network port. Bookmark "
1180+ "file not written.")
1181 try:
1182 os.remove(bookmark_file)
1183 except OSError:
1184
1185=== modified file 'desktopcouch/tests/test_local_files.py'
1186--- desktopcouch/tests/test_local_files.py 2009-08-04 12:31:15 +0000
1187+++ desktopcouch/tests/test_local_files.py 2009-08-21 21:57:37 +0000
1188@@ -1,28 +1,15 @@
1189 """testing desktopcouch/local_files.py module"""
1190
1191 import testtools
1192-import os
1193
1194 class TestLocalFiles(testtools.TestCase):
1195 """Testing that local files returns the right things"""
1196 def test_all_files_returned(self):
1197 "Does local_files list all the files that it needs to?"
1198 import desktopcouch.local_files
1199- for required in ["FILE_LOG", "FILE_INI", "FILE_PID", "FILE_STDOUT",
1200- "FILE_STDERR", "DIR_DB", "COUCH_EXE", "COUCH_EXEC_COMMAND"]:
1201+ for required in [
1202+ "FILE_LOG", "FILE_INI", "FILE_PID", "FILE_STDOUT",
1203+ "FILE_STDERR", "DIR_DB", "COUCH_EXE", "COUCH_EXEC_COMMAND"]:
1204 self.assertTrue(required in dir(desktopcouch.local_files))
1205
1206- def DISABLED_test_file_locations(self):
1207- """This stopped working when we split desktopcouch into its own
1208- top-level package."""
1209
1210- "Are the files in local_files actually correct?"
1211- # Only test one file; if one's right the others should be too
1212- import desktopcouch.local_files
1213- thisfolder = os.path.split(__file__)[0]
1214- tmpfolder = os.path.join(thisfolder, "..", "..", "..", "..", "tmp")
1215- pidfile = os.path.join(tmpfolder, "desktop-couchdb.pid")
1216- flatpidfile = os.path.realpath(pidfile)
1217- self.assertEqual(flatpidfile, desktopcouch.local_files.FILE_PID)
1218-
1219-
1220
1221=== modified file 'desktopcouch/tests/test_start_local_couchdb.py'
1222--- desktopcouch/tests/test_start_local_couchdb.py 2009-08-20 18:20:18 +0000
1223+++ desktopcouch/tests/test_start_local_couchdb.py 2009-08-21 21:57:37 +0000
1224@@ -3,7 +3,8 @@
1225 import testtools
1226 import os, tempfile, sys
1227 import desktopcouch
1228-sys.path.append(os.path.join(os.path.split(desktopcouch.__file__)[0], "..", "contrib"))
1229+sys.path.append(
1230+ os.path.join(os.path.split(desktopcouch.__file__)[0], "..", "contrib"))
1231 from mocker import Mocker
1232
1233 class TestUpdateDesignDocuments(testtools.TestCase):
1234@@ -16,37 +17,37 @@
1235 self.tmpdir = tempfile.mkdtemp(dir=branch_root)
1236 self.basedir = os.path.join(self.tmpdir, "desktop-couch")
1237 os.mkdir(self.basedir)
1238- DIRS = [
1239- "databases",
1240- "databases/nocfg",
1241- "databases/cfg",
1242- "databases/cfg_and_empty_design",
1243- "databases/cfg_and_empty_design/_design",
1244+ DIRS = [
1245+ "databases",
1246+ "databases/nocfg",
1247+ "databases/cfg",
1248+ "databases/cfg_and_empty_design",
1249+ "databases/cfg_and_empty_design/_design",
1250 "databases/cfg_and_design_no_views",
1251- "databases/cfg_and_design_no_views/_design",
1252- "databases/cfg_and_design_no_views/_design/doc1",
1253- "databases/cfg_and_design_no_views/_design/doc1/views",
1254+ "databases/cfg_and_design_no_views/_design",
1255+ "databases/cfg_and_design_no_views/_design/doc1",
1256+ "databases/cfg_and_design_no_views/_design/doc1/views",
1257 "databases/cfg_and_design_one_view_no_map",
1258- "databases/cfg_and_design_one_view_no_map/_design",
1259- "databases/cfg_and_design_one_view_no_map/_design/doc1",
1260- "databases/cfg_and_design_one_view_no_map/_design/doc1/views",
1261- "databases/cfg_and_design_one_view_no_map/_design/doc1/views/view1",
1262+ "databases/cfg_and_design_one_view_no_map/_design",
1263+ "databases/cfg_and_design_one_view_no_map/_design/doc1",
1264+ "databases/cfg_and_design_one_view_no_map/_design/doc1/views",
1265+ "databases/cfg_and_design_one_view_no_map/_design/doc1/views/view1",
1266 "databases/cfg_and_design_one_view_map_no_reduce",
1267- "databases/cfg_and_design_one_view_map_no_reduce/_design",
1268- "databases/cfg_and_design_one_view_map_no_reduce/_design/doc1",
1269- "databases/cfg_and_design_one_view_map_no_reduce/_design/doc1/views",
1270- "databases/cfg_and_design_one_view_map_no_reduce/_design/doc1/views/view1",
1271+ "databases/cfg_and_design_one_view_map_no_reduce/_design",
1272+ "databases/cfg_and_design_one_view_map_no_reduce/_design/doc1",
1273+ "databases/cfg_and_design_one_view_map_no_reduce/_design/doc1/views",
1274+ "databases/cfg_and_design_one_view_map_no_reduce/_design/doc1/views/view1",
1275 "databases/cfg_and_design_one_view_map_reduce",
1276- "databases/cfg_and_design_one_view_map_reduce/_design",
1277- "databases/cfg_and_design_one_view_map_reduce/_design/doc1",
1278- "databases/cfg_and_design_one_view_map_reduce/_design/doc1/views",
1279- "databases/cfg_and_design_one_view_map_reduce/_design/doc1/views/view1",
1280+ "databases/cfg_and_design_one_view_map_reduce/_design",
1281+ "databases/cfg_and_design_one_view_map_reduce/_design/doc1",
1282+ "databases/cfg_and_design_one_view_map_reduce/_design/doc1/views",
1283+ "databases/cfg_and_design_one_view_map_reduce/_design/doc1/views/view1",
1284 "databases/cfg_and_design_two_views_map_reduce",
1285- "databases/cfg_and_design_two_views_map_reduce/_design",
1286- "databases/cfg_and_design_two_views_map_reduce/_design/doc1",
1287- "databases/cfg_and_design_two_views_map_reduce/_design/doc1/views",
1288- "databases/cfg_and_design_two_views_map_reduce/_design/doc1/views/view1",
1289- "databases/cfg_and_design_two_views_map_reduce/_design/doc1/views/view2",
1290+ "databases/cfg_and_design_two_views_map_reduce/_design",
1291+ "databases/cfg_and_design_two_views_map_reduce/_design/doc1",
1292+ "databases/cfg_and_design_two_views_map_reduce/_design/doc1/views",
1293+ "databases/cfg_and_design_two_views_map_reduce/_design/doc1/views/view1",
1294+ "databases/cfg_and_design_two_views_map_reduce/_design/doc1/views/view2",
1295 ]
1296 FILES = {
1297 "databases/cfg/database.cfg": "",
1298@@ -78,7 +79,7 @@
1299 fp = open(os.path.join(self.basedir, f), "w")
1300 fp.write(data)
1301 fp.close()
1302-
1303+
1304 def tearDown(self):
1305 # delete temp folder
1306 for root, dirs, files in os.walk(self.tmpdir, topdown=False):
1307@@ -86,10 +87,10 @@
1308 os.remove(os.path.join(root, name))
1309 for name in dirs:
1310 os.rmdir(os.path.join(root, name))
1311- os.rmdir(self.tmpdir)
1312+ os.rmdir(self.tmpdir)
1313
1314 def test_create_databases_and_design_docs(self):
1315- """Are databases and design documents correctly
1316+ """Are databases and design documents correctly
1317 created from the filesystem?"""
1318 # poke local_files so that it returns our temp folder
1319 os.environ['XDG_DATA_HOME'] = self.tmpdir
1320@@ -101,11 +102,11 @@
1321 import xdg.BaseDirectory
1322 reload(xdg.BaseDirectory)
1323
1324-
1325+
1326 # Mock CouchDatabase
1327 mocker = Mocker()
1328 couchdb = mocker.replace("desktopcouch.records.server.CouchDatabase")
1329-
1330+
1331 # databases that should be created
1332 couchdb("cfg", create=True)
1333 couchdb("cfg_and_empty_design", create=True)
1334@@ -114,28 +115,28 @@
1335 couchdb("cfg_and_design_one_view_map_no_reduce", create=True)
1336 dbmock1 = mocker.mock()
1337 mocker.result(dbmock1)
1338- dbmock1.add_view("view1", "cfg_and_design_one_view_map_no_reduce:map",
1339+ dbmock1.add_view("view1", "cfg_and_design_one_view_map_no_reduce:map",
1340 None, "doc1")
1341 couchdb("cfg_and_design_one_view_map_reduce", create=True)
1342 dbmock2 = mocker.mock()
1343 mocker.result(dbmock2)
1344- dbmock2.add_view("view1", "cfg_and_design_one_view_map_reduce:map",
1345+ dbmock2.add_view("view1", "cfg_and_design_one_view_map_reduce:map",
1346 "cfg_and_design_one_view_map_reduce:reduce", "doc1")
1347 couchdb("cfg_and_design_two_views_map_reduce", create=True)
1348 dbmock3 = mocker.mock()
1349 mocker.result(dbmock3)
1350- dbmock3.add_view("view1", "cfg_and_design_two_views_map_reduce:map1",
1351+ dbmock3.add_view("view1", "cfg_and_design_two_views_map_reduce:map1",
1352 "cfg_and_design_two_views_map_reduce:reduce1", "doc1")
1353- dbmock3.add_view("view2", "cfg_and_design_two_views_map_reduce:map2",
1354+ dbmock3.add_view("view2", "cfg_and_design_two_views_map_reduce:map2",
1355 "cfg_and_design_two_views_map_reduce:reduce2", "doc1")
1356-
1357+
1358 # actually call update_design_documents to confirm that it creates
1359 # all the right things
1360 mocker.replay()
1361 from desktopcouch.start_local_couchdb import update_design_documents
1362 update_design_documents()
1363-
1364+
1365 mocker.restore()
1366 mocker.verify()
1367-
1368+
1369

Subscribers

People subscribed via source and target branches