Merge lp://qastaging/~rick-rickspencer3/desktopcouch/CouchWidget-tests-and-robustness into lp://qastaging/desktopcouch

Proposed by Rick Spencer
Status: Merged
Approved by: Rodrigo Moya
Approved revision: 44
Merged at revision: not available
Proposed branch: lp://qastaging/~rick-rickspencer3/desktopcouch/CouchWidget-tests-and-robustness
Merge into: lp://qastaging/desktopcouch
Diff against target: None lines
To merge this branch: bzr merge lp://qastaging/~rick-rickspencer3/desktopcouch/CouchWidget-tests-and-robustness
Reviewer Review Type Date Requested Status
Rodrigo Moya (community) Approve
Eric Casteleijn (community) Approve
Review via email: mp+10488@code.qastaging.launchpad.net

Commit message

This commit is focused on couchwidget.py. It fixes some bugs, and adds tests for CouchWidget. It also modifies contactspicker.py to use the desktopcouch api and to not break with the CouchWidget changes.

To post a comment you must log in.
Revision history for this message
Rick Spencer (rick-rickspencer3) wrote :

Note that this branch breaks the CouchWidget API by requiring a database be specified when the widget is created.

This branch fixes bug 412266.

This branch adds more tests for CouchWidget, and improves the tests that existed.

Revision history for this message
Rick Spencer (rick-rickspencer3) wrote :

Note that this branch breaks the CouchWidget API by requiring a database be specified when the widget is created.

This branch fixes bug 412266.

This branch adds more tests for CouchWidget, and improves the tests that existed.

42. By Rick Spencer

modified contactspicker.py to accomdate api changes and also to not use static local ip address

43. By Rick Spencer

added nicer titles to contactspicker.py

44. By Rick Spencer

removed now eroneous doc comment, and made contactspicker titles look a little nicer

Revision history for this message
Eric Casteleijn (thisfred) wrote :

The code looks good and passes tests, but I see a lot of PEP-8 violations.

Specifically: long lines (max 79 chars + /n), and missing spaces after punctuation like colons in dicts and commas.

review: Approve
Revision history for this message
Rodrigo Moya (rodrigo-moya) wrote :

> Note that this branch breaks the CouchWidget API by requiring a database be
> specified when the widget is created.
>
please change then the contactspicker.py CouchWidget creation, if not it will break when you merge this branch

review: Needs Fixing
Revision history for this message
Rick Spencer (rick-rickspencer3) wrote :

> > Note that this branch breaks the CouchWidget API by requiring a database be
> > specified when the widget is created.
> >
> please change then the contactspicker.py CouchWidget creation, if not it will
> break when you merge this branch

I did so in commit #43. I fixed a couple of other issues there as well. Perhaps I didn't do the merge proposal correctly, as I pushed those changes *after* making the merge proposal. Sorry about that.

Cheers, Rick

Revision history for this message
Rodrigo Moya (rodrigo-moya) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'desktopcouch/records/couchwidget.py'
--- desktopcouch/records/couchwidget.py 2009-08-19 23:01:09 +0000
+++ desktopcouch/records/couchwidget.py 2009-08-20 21:32:18 +0000
@@ -26,24 +26,46 @@
26class CouchWidget(gtk.TreeView):26class CouchWidget(gtk.TreeView):
27 __gtype_name__ = "CouchWidget"27 __gtype_name__ = "CouchWidget"
2828
29 def __init__(self, server_ip = 'http://127.0.0.1:5984/'):29 def __init__(self, database_name, record_type = None, headings = None):
30 """Create a new Couchwidget30 """Create a new Couchwidget
31 arguments:
32 database_name - specify the name of the database in the desktop
33 couchdb to use. If the specified database does not exist, it
34 will be created.
35
31 optional arguments:36 optional arguments:
32 server_ip - specify and ip and port for the server location.37 record_type - a string to specify the record_type to use in
33 Defaults to http://127.0.0.1:598438 retrieving and creating records. Note that if no records are
34 39 set the headings argument must also be used or a RuntimeError
40 will result.
41
42 headings - a list of strings specifying headings to use in
43 the columns of the CouchWidget.
44
45 Note that the CouchWidget uses headings for keys, and visa versa.
46 If a record does not contain a value for a specified value
47 the CouchWidget will simply display an empty string for the
48 value. If the widget is set to editable, the user will be able
49 to add values to the database.
50
35 """51 """
3652
37 gtk.TreeView.__init__(self)53 gtk.TreeView.__init__(self)
3854
39 #assume a local server
40 self.server_ip = server_ip
41
42 #set up the default values55 #set up the default values
43 self.__db = None56 if type(database_name) is not type(str()):
57 raise TypeError("database_name is required and must be a string")
58
59 #set up default values
44 self.__record_type = None60 self.__record_type = None
45 self.__headings = None61 self.__headings = headings
46 self.__editable = False62 self.__editable = False
63
64 #set the datatabase
65 self.database = database_name
66 if record_type is not None:
67 self.record_type = record_type
68
47 self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)69 self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
4870
49 @property71 @property
@@ -84,7 +106,7 @@
84106
85 #refresh the treeview if possible107 #refresh the treeview if possible
86 if self.record_type != None:108 if self.record_type != None:
87 self.__populate_treeview()(self.record_type)109 self.__populate_treeview()
88110
89 @property111 @property
90 def database(self):112 def database(self):
@@ -96,7 +118,7 @@
96118
97 @database.setter119 @database.setter
98 def database(self, db_name):120 def database(self, db_name):
99 self.__db = CouchDatabase(db_name, uri=self.server_ip, create=True)121 self.__db = CouchDatabase(db_name, create=True)
100122
101 if self.record_type != None:123 if self.record_type != None:
102 self.__populate_treeview()(self.record_type)124 self.__populate_treeview()(self.record_type)
@@ -119,30 +141,51 @@
119141
120 def __populate_treeview(self):142 def __populate_treeview(self):
121 #if the database is not set up, just return143 #if the database is not set up, just return
122 if self.__db == None or self.__headings == None:144 if self.__db == None:
123 return145 return
124146
125 #refresh the model structure147 #the cases with headings are complex and hacky
126 self.__reset_model()148 #there are the following cases:
149 #1. headings have not been set and cannot be inferred
150 #2. headings have been previously set
151 #3. headings should be inferred from results
152
127153
128 #retrieve the docs for the record_type, if any154 #retrieve the docs for the record_type, if any
129 results = self.__db.get_records(record_type=self.__record_type,create_view=True)155 results = self.__db.get_records(record_type=self.__record_type,create_view=True)
130156
157 #test for headings case 1 and raise an exception
158 if len(results) < 1 and self.headings == None:
159 raise RuntimeError("""Cannot infer columns for CouchWidget.
160 Ensure that records exist, or define columns using
161 CouchWidget.headings property.
162 """)
163
164 #test for case 2, and set up the model
165 if self.headings is not None:
166 self.__reset_model()
167
131 #if headings are already assigned, set up headings and columns168 #if headings are already assigned, set up headings and columns
169 #for headings case 2 with or without results
132 if self.headings != None:170 if self.headings != None:
133 self.__make_headings()171 self.__make_headings()
134172
135 first_row = True173 first_row = True
136 for r in results:174 for r in results:
175 #handle headings case 3
137 #if headings are not set up, infer them from 176 #if headings are not set up, infer them from
138 #the first stored record
139 if self.headings == None and first_row:177 if self.headings == None and first_row:
140 self.headings = []178 self.headings = []
141 for k in r.value.keys():179 for k in r.value.keys():
142 if not k.startswith("_") and k != "record_type":180 if not k.startswith("_") and k != "record_type":
143 self.headings.append(k)181 self.headings.append(k)
144 #now set up the columns and headers182 #now set up the columns and headers
145 self.__make_headings() 183 self.__make_headings()
184
185 #in headings case 3 the model has not been set yet
186 #so do that now
187 self.__reset_model()
188
146 first_row = False189 first_row = False
147190
148 #lists have to match the list_store columns in length191 #lists have to match the list_store columns in length
@@ -187,6 +230,9 @@
187230
188 """231 """
189232
233 #TODO: add gaurd conditions
234 #throw if no database is set
235
190 #lists have to match the list_store columns in length236 #lists have to match the list_store columns in length
191 #note that the last value is reserved for the doc_id237 #note that the last value is reserved for the doc_id
192 col_count = len(self.headings) + 1238 col_count = len(self.headings) + 1
@@ -306,7 +352,7 @@
306 This function is typically called when properties are set352 This function is typically called when properties are set
307353
308 """354 """
309355
310 #remove the current columns from the TreeView356 #remove the current columns from the TreeView
311 cols = self.get_columns()357 cols = self.get_columns()
312 for c in cols:358 for c in cols:
@@ -319,7 +365,7 @@
319365
320 def __make_headings(self):366 def __make_headings(self):
321 """ __make_headings - internal funciton do not call direclty367 """ __make_headings - internal funciton do not call direclty
322 Sets up the headings and columnss for the TreeView.368 Sets up the headings and columns for the TreeView.
323369
324 """370 """
325371
@@ -408,19 +454,11 @@
408 win.add(vbox)454 win.add(vbox)
409455
410 #create a test widget with test database values456 #create a test widget with test database values
411 cw = CouchWidget()457 cw = CouchWidget("couch_widget_test", record_type = "test_record_type", headings = ["Key1","Key2","Key3","Key4"])
412 cw.database = "couch_widget_test"
413458
414 #allow editing459 #allow editing
415 cw.editable = True460 cw.editable = True
416461
417 #create headers/keys
418 cw.headings = ["Key1","Key2","Key3","Key4"]
419
420 #set the record_type for the TreeView
421 #it will not populate without this value being set
422 cw.record_type = "test_record_type"
423
424 #create a row with all four columns set462 #create a row with all four columns set
425 cw.append_row(["val1","val2","val3","val4"])463 cw.append_row(["val1","val2","val3","val4"])
426464
@@ -442,12 +480,10 @@
442 tv.show()480 tv.show()
443 cw.connect("cursor-changed",__show_selected, (tv,cw))481 cw.connect("cursor-changed",__show_selected, (tv,cw))
444482
445
446 #create ui for testing selection483 #create ui for testing selection
447 id_vbox = gtk.VBox(False, 5)484 id_vbox = gtk.VBox(False, 5)
448 id_vbox.show()485 id_vbox.show()
449486
450
451 fb_lbl = gtk.Label("paste ids into the edit box to select them")487 fb_lbl = gtk.Label("paste ids into the edit box to select them")
452 fb_lbl.show()488 fb_lbl.show()
453489
454490
=== modified file 'desktopcouch/records/tests/test_couchwidget.py'
--- desktopcouch/records/tests/test_couchwidget.py 2009-08-19 23:01:09 +0000
+++ desktopcouch/records/tests/test_couchwidget.py 2009-08-20 21:32:18 +0000
@@ -19,6 +19,7 @@
19"""Tests for the couchwidget object"""19"""Tests for the couchwidget object"""
2020
21from testtools import TestCase21from testtools import TestCase
22from desktopcouch.records.record import Record
22from desktopcouch.records.server import CouchDatabase23from desktopcouch.records.server import CouchDatabase
23from desktopcouch.records.couchwidget import CouchWidget24from desktopcouch.records.couchwidget import CouchWidget
2425
@@ -28,59 +29,170 @@
28 self.dbname = "couch_widget_test"29 self.dbname = "couch_widget_test"
29 self.record_type = "test_record_type"30 self.record_type = "test_record_type"
3031
31 def test_headings_first(self):32 def test_constructor_gaurded(self):
32 #create a test widget with test database values33 """ensure that couchwidget cannot be constructed without a database name"""
33 cw = CouchWidget()34 try:
34 cw.database = self.dbname35 cw = CouchWidget(None)
3536 except TypeError, inst:
36 #allow editing37 self.assertEqual(inst.args[0],"database_name is required and must be a string")
37 cw.editable = True38
3839 def test_new_rows_with_headings(self):
39 #create headers/keys40 """Test a simple creating a couchwidget """
40 cw.headings = ["Key1","Key2","Key3","Key4"]41
4142 #create a test widget with test database values
42 #set the record_type for the TreeView43 cw = CouchWidget(self.dbname)
43 #it will not populate without this value being set44
44 cw.record_type = self.record_type45 #allow editing
4546 cw.editable = True
46 #create a row with all four columns set47
47 cw.append_row(["val1","val2","val3","val4"])48 #create headers/keys
4849 cw.headings = ["Key1","Key2","Key3","Key4"]
49 #create a row with only the second column set50
50 cw.append_row(["","val2"])51 #set the record_type for the TreeView
5152 #it will not populate without this value being set
52 #create an empty row (which will not be saved until the user edits it)53 cw.record_type = self.record_type
53 cw.append_row([])54
5455 #create a row with all four columns set
55 self.assertEqual(cw.record_type, self.record_type)56 cw.append_row(["val1","val2","val3","val4"])
56 self.__delete_db()57
5758 #create a row with only the second column set
58 def test_record_type_first(self):59 cw.append_row(["","val2"])
59 #create a test widget with test database values60
60 cw = CouchWidget()61 #create an empty row (which will not be saved until the user edits it)
61 cw.database = self.dbname62 cw.append_row([])
6263
63 #allow editing64 #if this all worked, there should be three rows in the model
64 cw.editable = True65 model = cw.get_model()
6566 self.assertEqual(len(model), 3)
66 #set the record_type for the TreeView67
67 #it will not populate without this value being set68 #clean up for the next test
68 cw.record_type = self.record_type69 self.__delete_db()
6970
70 #create headers/keys71 def test_no_headings_or_stored_records(self):
71 cw.headings = ["Key1","Key2","Key3","Key4"]72 """test when there is no defined headings and no stored records
7273 to infer headings from. Should raise a proper exception.
73 #create a row with all four columns set74 """
74 cw.append_row(["val1","val2","val3","val4"])75
7576 try:
76 #create a row with only the second column set77 #create a test widget with test database values
77 cw.append_row(["","val2"])78 cw = CouchWidget(self.dbname)
7879
79 #create an empty row (which will not be saved until the user edits it)80 #set the record_type for the TreeView
80 cw.append_row([])81 #it will not populate without this value being set
8182 cw.record_type = self.record_type
82 self.assertEqual(cw.record_type, self.record_type)83
83 self.__delete_db() 84 #create a row with all four columns set
85 cw.append_row(["val1","val2","val3","val4"])
86
87 #create a row with only the second column set
88 cw.append_row(["","val2"])
89
90 #create an empty row (which will not be saved until the user edits it)
91 cw.append_row([])
92
93 #if this all worked, there should be three rows in the model
94 model = cw.get_model()
95
96 #should be catching the following exception
97 except RuntimeError, inst:
98 self.assertEquals(inst.args[0].find("Cannot infer columns for CouchWidget"),0)
99
100 #clean up for the next test
101 self.__delete_db()
102
103 def test_all_from_database(self):
104 #create some records
105 db = CouchDatabase(self.dbname, create=True)
106 db.put_record(Record({"key1_1":"val1_1","key1_2":"val1_2","key1_3":"val1_3","record_type":self.record_type}))
107 db.put_record(Record({"key2_1":"val2_1","key2_2":"val2_2","key2_3":"val2_3","record_type":self.record_type}))
108
109 #build the couchwidget
110 cw = CouchWidget(self.dbname)
111 cw.record_type = self.record_type
112 #make sure there are three columns and two rows
113 self.assertEqual(cw.get_model().get_n_columns(),4)
114 self.assertEqual(len(cw.get_model()),2)
115
116 #clean up for the next test
117 self.__delete_db()
118
119 def test_single_col_from_database(self):
120 #create some records
121 db = CouchDatabase(self.dbname, create=True)
122 db.put_record(Record({"key1_1":"val1_1","key1_2":"val1_2","key1_3":"val1_3","record_type":self.record_type}))
123 db.put_record(Record({"key1_1":"val2_1","key1_2":"val2_2","key1_3":"val2_3","record_type":self.record_type}))
124
125 #build the couchwidget
126 cw = CouchWidget(self.dbname)
127 cw.headings = ["key1_1"]
128 cw.record_type = self.record_type
129 #make sure there are three columns and two rows
130 self.assertEqual(cw.get_model().get_n_columns(),2)
131 self.assertEqual(len(cw.get_model()),2)
132
133 #clean up for the next test
134 self.__delete_db()
135
136 def test_optional_record_type_arg(self):
137 """Test a simple creating a couchwidget """
138 #create some records
139 db = CouchDatabase(self.dbname, create=True)
140 db.put_record(Record({"key1_1":"val1_1","key1_2":"val1_2","key1_3":"val1_3","record_type":self.record_type}))
141 db.put_record(Record({"key2_1":"val2_1","key2_2":"val2_2","key2_3":"val2_3","record_type":self.record_type}))
142
143 #create a test widget with test database values
144 cw = CouchWidget(self.dbname, record_type = self.record_type)
145
146 #make sure there are three columns and two rows
147 self.assertEqual(cw.get_model().get_n_columns(),4)
148 self.assertEqual(len(cw.get_model()),2)
149
150 #clean up for the next test
151 self.__delete_db()
152
153 def test_optional_args_no_stored_records(self):
154 """Test a simple creating a couchwidget """
155
156 #create a test widget with test database values
157 cw = CouchWidget(self.dbname, record_type = self.record_type, headings = ["Key1","Key2","Key3","Key4"])
158
159
160 #create a row with all four columns set
161 cw.append_row(["val1","val2","val3","val4"])
162
163 #create a row with only the second column set
164 cw.append_row(["","val2"])
165
166 #create an empty row (which will not be saved until the user edits it)
167 cw.append_row([])
168
169 #if this all worked, there should be three rows in the model
170 model = cw.get_model()
171 self.assertEqual(len(model), 3)
172
173 #clean up for the next test
174 self.__delete_db()
175
176 def test_programatically_add_row(self):
177 """test appending different sized rows programatically"""
178 #create some records
179 db = CouchDatabase(self.dbname, create=True)
180 db.put_record(Record({"key1_1":"val1_1","key1_2":"val1_2","key1_3":"val1_3","record_type":self.record_type}))
181 db.put_record(Record({"key2_1":"val2_1","key2_2":"val2_2","key2_3":"val2_3","record_type":self.record_type}))
182
183 #create a test widget with test database values
184 cw = CouchWidget(self.dbname, record_type = self.record_type)
185
186 #allow editing
187 cw.append_row(["boo","ray"])
188
189 #make sure there are three columns and two rows
190 self.assertEqual(cw.get_model().get_n_columns(),4)
191 self.assertEqual(len(cw.get_model()),3)
192
193 #clean up for the next test
194 self.__delete_db()
195
84196
85 def tearDown(self):197 def tearDown(self):
86 """tear down each test"""198 """tear down each test"""
@@ -91,4 +203,5 @@
91 db = CouchDatabase(self.dbname, create=True)203 db = CouchDatabase(self.dbname, create=True)
92 del db._server[self.dbname]204 del db._server[self.dbname]
93205
206
94 207

Subscribers

People subscribed via source and target branches