Mercurial > p > roundup > code
comparison roundup/cgi/client.py @ 1291:bf8b2380adb3
added CGI :remove:<propname> and :add:<propname>...
...which specify item ids to remove / add in <propname> multilink.
(is used in issue message display, allowing removal of messages)
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Fri, 18 Oct 2002 03:34:58 +0000 |
| parents | ad8de51d7cd5 |
| children | 71be6588904f |
comparison
equal
deleted
inserted
replaced
| 1290:fc451828f971 | 1291:bf8b2380adb3 |
|---|---|
| 1 # $Id: client.py,v 1.54 2002-10-17 06:11:25 richard Exp $ | 1 # $Id: client.py,v 1.55 2002-10-18 03:34:58 richard Exp $ |
| 2 | 2 |
| 3 __doc__ = """ | 3 __doc__ = """ |
| 4 WWW request handler (also used in the stand-alone server). | 4 WWW request handler (also used in the stand-alone server). |
| 5 """ | 5 """ |
| 6 | 6 |
| 661 the :note if it's supplied. | 661 the :note if it's supplied. |
| 662 | 662 |
| 663 :required=property,property,... | 663 :required=property,property,... |
| 664 The named properties are required to be filled in the form. | 664 The named properties are required to be filled in the form. |
| 665 | 665 |
| 666 :remove:<propname>=id(s) | |
| 667 The ids will be removed from the multilink property. | |
| 668 :add:<propname>=id(s) | |
| 669 The ids will be added to the multilink property. | |
| 670 | |
| 666 ''' | 671 ''' |
| 667 cl = self.db.classes[self.classname] | 672 cl = self.db.classes[self.classname] |
| 668 | 673 |
| 669 # parse the props from the form | 674 # parse the props from the form |
| 670 try: | 675 try: |
| 1139 def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')): | 1144 def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')): |
| 1140 ''' Pull properties for the given class out of the form. | 1145 ''' Pull properties for the given class out of the form. |
| 1141 | 1146 |
| 1142 If a ":required" parameter is supplied, then the names property values | 1147 If a ":required" parameter is supplied, then the names property values |
| 1143 must be supplied or a ValueError will be raised. | 1148 must be supplied or a ValueError will be raised. |
| 1149 | |
| 1150 Other special form values: | |
| 1151 :remove:<propname>=id(s) | |
| 1152 The ids will be removed from the multilink property. | |
| 1153 :add:<propname>=id(s) | |
| 1154 The ids will be added to the multilink property. | |
| 1144 ''' | 1155 ''' |
| 1145 required = [] | 1156 required = [] |
| 1146 if form.has_key(':required'): | 1157 if form.has_key(':required'): |
| 1147 value = form[':required'] | 1158 value = form[':required'] |
| 1148 if isinstance(value, type([])): | 1159 if isinstance(value, type([])): |
| 1152 | 1163 |
| 1153 props = {} | 1164 props = {} |
| 1154 keys = form.keys() | 1165 keys = form.keys() |
| 1155 properties = cl.getprops() | 1166 properties = cl.getprops() |
| 1156 for key in keys: | 1167 for key in keys: |
| 1157 if not properties.has_key(key): | 1168 # see if we're performing a special multilink action |
| 1169 mlaction = 'set' | |
| 1170 if key.startswith(':remove:'): | |
| 1171 propname = key[8:] | |
| 1172 mlaction = 'remove' | |
| 1173 elif key.startswith(':add:'): | |
| 1174 propname = key[5:] | |
| 1175 mlaction = 'add' | |
| 1176 else: | |
| 1177 propname = key | |
| 1178 | |
| 1179 | |
| 1180 # does the property exist? | |
| 1181 if not properties.has_key(propname): | |
| 1182 if mlaction != 'set': | |
| 1183 raise ValueError, 'You have submitted a remove action for'\ | |
| 1184 ' the property "%s" which doesn\'t exist'%propname | |
| 1158 continue | 1185 continue |
| 1159 proptype = properties[key] | 1186 proptype = properties[propname] |
| 1160 | 1187 |
| 1161 # Get the form value. This value may be a MiniFieldStorage or a list | 1188 # Get the form value. This value may be a MiniFieldStorage or a list |
| 1162 # of MiniFieldStorages. | 1189 # of MiniFieldStorages. |
| 1163 value = form[key] | 1190 value = form[key] |
| 1191 | |
| 1192 print (mlaction, propname, value) | |
| 1164 | 1193 |
| 1165 # make sure non-multilinks only get one value | 1194 # make sure non-multilinks only get one value |
| 1166 if not isinstance(proptype, hyperdb.Multilink): | 1195 if not isinstance(proptype, hyperdb.Multilink): |
| 1167 if isinstance(value, type([])): | 1196 if isinstance(value, type([])): |
| 1168 raise ValueError, 'You have submitted more than one value'\ | 1197 raise ValueError, 'You have submitted more than one value'\ |
| 1169 ' for the %s property'%key | 1198 ' for the %s property'%propname |
| 1170 # we've got a MiniFieldStorage, so pull out the value and strip | 1199 # we've got a MiniFieldStorage, so pull out the value and strip |
| 1171 # surrounding whitespace | 1200 # surrounding whitespace |
| 1172 value = value.value.strip() | 1201 value = value.value.strip() |
| 1173 | 1202 |
| 1174 if isinstance(proptype, hyperdb.String): | 1203 if isinstance(proptype, hyperdb.String): |
| 1178 value = fixNewlines(value) | 1207 value = fixNewlines(value) |
| 1179 elif isinstance(proptype, hyperdb.Password): | 1208 elif isinstance(proptype, hyperdb.Password): |
| 1180 if not value: | 1209 if not value: |
| 1181 # ignore empty password values | 1210 # ignore empty password values |
| 1182 continue | 1211 continue |
| 1183 if not form.has_key('%s:confirm'%key): | 1212 if not form.has_key('%s:confirm'%propname): |
| 1184 raise ValueError, 'Password and confirmation text do not match' | 1213 raise ValueError, 'Password and confirmation text do not match' |
| 1185 confirm = form['%s:confirm'%key] | 1214 confirm = form['%s:confirm'%propname] |
| 1186 if isinstance(confirm, type([])): | 1215 if isinstance(confirm, type([])): |
| 1187 raise ValueError, 'You have submitted more than one value'\ | 1216 raise ValueError, 'You have submitted more than one value'\ |
| 1188 ' for the %s property'%key | 1217 ' for the %s property'%propname |
| 1189 if value != confirm.value: | 1218 if value != confirm.value: |
| 1190 raise ValueError, 'Password and confirmation text do not match' | 1219 raise ValueError, 'Password and confirmation text do not match' |
| 1191 value = password.Password(value) | 1220 value = password.Password(value) |
| 1192 elif isinstance(proptype, hyperdb.Date): | 1221 elif isinstance(proptype, hyperdb.Date): |
| 1193 if value: | 1222 if value: |
| 1194 value = date.Date(form[key].value.strip()) | 1223 value = date.Date(value.value.strip()) |
| 1195 else: | 1224 else: |
| 1196 continue | 1225 continue |
| 1197 elif isinstance(proptype, hyperdb.Interval): | 1226 elif isinstance(proptype, hyperdb.Interval): |
| 1198 if value: | 1227 if value: |
| 1199 value = date.Interval(form[key].value.strip()) | 1228 value = date.Interval(value.value.strip()) |
| 1200 else: | 1229 else: |
| 1201 continue | 1230 continue |
| 1202 elif isinstance(proptype, hyperdb.Link): | 1231 elif isinstance(proptype, hyperdb.Link): |
| 1203 # see if it's the "no selection" choice | 1232 # see if it's the "no selection" choice |
| 1204 if value == '-1': | 1233 if value == '-1': |
| 1209 if not num_re.match(value): | 1238 if not num_re.match(value): |
| 1210 try: | 1239 try: |
| 1211 value = db.classes[link].lookup(value) | 1240 value = db.classes[link].lookup(value) |
| 1212 except KeyError: | 1241 except KeyError: |
| 1213 raise ValueError, _('property "%(propname)s": ' | 1242 raise ValueError, _('property "%(propname)s": ' |
| 1214 '%(value)s not a %(classname)s')%{'propname':key, | 1243 '%(value)s not a %(classname)s')%{ |
| 1215 'value': value, 'classname': link} | 1244 'propname': propname, 'value': value, |
| 1245 'classname': link} | |
| 1216 except TypeError, message: | 1246 except TypeError, message: |
| 1217 raise ValueError, _('you may only enter ID values ' | 1247 raise ValueError, _('you may only enter ID values ' |
| 1218 'for property "%(propname)s": %(message)s')%{ | 1248 'for property "%(propname)s": %(message)s')%{ |
| 1219 'propname':key, 'message': message} | 1249 'propname': propname, 'message': message} |
| 1220 elif isinstance(proptype, hyperdb.Multilink): | 1250 elif isinstance(proptype, hyperdb.Multilink): |
| 1221 if isinstance(value, type([])): | 1251 if isinstance(value, type([])): |
| 1222 # it's a list of MiniFieldStorages | 1252 # it's a list of MiniFieldStorages |
| 1223 value = [i.value.strip() for i in value] | 1253 value = [i.value.strip() for i in value] |
| 1224 else: | 1254 else: |
| 1233 try: | 1263 try: |
| 1234 entry = db.classes[link].lookup(entry) | 1264 entry = db.classes[link].lookup(entry) |
| 1235 except KeyError: | 1265 except KeyError: |
| 1236 raise ValueError, _('property "%(propname)s": ' | 1266 raise ValueError, _('property "%(propname)s": ' |
| 1237 '"%(value)s" not an entry of %(classname)s')%{ | 1267 '"%(value)s" not an entry of %(classname)s')%{ |
| 1238 'propname':key, 'value': entry, 'classname': link} | 1268 'propname': propname, 'value': entry, |
| 1269 'classname': link} | |
| 1239 except TypeError, message: | 1270 except TypeError, message: |
| 1240 raise ValueError, _('you may only enter ID values ' | 1271 raise ValueError, _('you may only enter ID values ' |
| 1241 'for property "%(propname)s": %(message)s')%{ | 1272 'for property "%(propname)s": %(message)s')%{ |
| 1242 'propname':key, 'message': message} | 1273 'propname': propname, 'message': message} |
| 1243 l.append(entry) | 1274 l.append(entry) |
| 1244 l.sort() | 1275 l.sort() |
| 1245 value = l | 1276 |
| 1277 # now use that list of ids to modify the multilink | |
| 1278 if mlaction == 'set': | |
| 1279 value = l | |
| 1280 else: | |
| 1281 # we're modifying the list - get the current list of ids | |
| 1282 try: | |
| 1283 existing = cl.get(nodeid, propname) | |
| 1284 except KeyError: | |
| 1285 existing = [] | |
| 1286 if mlaction == 'remove': | |
| 1287 # remove - handle situation where the id isn't in the list | |
| 1288 for entry in l: | |
| 1289 try: | |
| 1290 existing.remove(entry) | |
| 1291 except ValueError: | |
| 1292 raise ValueError, _('property "%(propname)s": ' | |
| 1293 '"%(value)s" not currently in list')%{ | |
| 1294 'propname': propname, 'value': entry} | |
| 1295 else: | |
| 1296 # add - easy, just don't dupe | |
| 1297 for entry in l: | |
| 1298 if entry not in existing: | |
| 1299 existing.append(entry) | |
| 1300 value = existing | |
| 1301 value.sort() | |
| 1302 | |
| 1246 elif isinstance(proptype, hyperdb.Boolean): | 1303 elif isinstance(proptype, hyperdb.Boolean): |
| 1247 props[key] = value = value.lower() in ('yes', 'true', 'on', '1') | 1304 value = value.lower() in ('yes', 'true', 'on', '1') |
| 1305 props[propname] = value | |
| 1248 elif isinstance(proptype, hyperdb.Number): | 1306 elif isinstance(proptype, hyperdb.Number): |
| 1249 props[key] = value = int(value) | 1307 props[propname] = value = int(value) |
| 1250 | 1308 |
| 1251 # register this as received if required? | 1309 # register this as received if required? |
| 1252 if key in required and value is not None: | 1310 if propname in required and value is not None: |
| 1253 required.remove(key) | 1311 required.remove(propname) |
| 1254 | 1312 |
| 1255 # get the old value | 1313 # get the old value |
| 1256 if nodeid: | 1314 if nodeid: |
| 1257 try: | 1315 try: |
| 1258 existing = cl.get(nodeid, key) | 1316 existing = cl.get(nodeid, propname) |
| 1259 except KeyError: | 1317 except KeyError: |
| 1260 # this might be a new property for which there is no existing | 1318 # this might be a new property for which there is no existing |
| 1261 # value | 1319 # value |
| 1262 if not properties.has_key(key): raise | 1320 if not properties.has_key(propname): |
| 1321 raise | |
| 1263 | 1322 |
| 1264 # if changed, set it | 1323 # if changed, set it |
| 1265 if value != existing: | 1324 if value != existing: |
| 1266 props[key] = value | 1325 props[propname] = value |
| 1267 else: | 1326 else: |
| 1268 props[key] = value | 1327 props[propname] = value |
| 1269 | 1328 |
| 1270 # see if all the required properties have been supplied | 1329 # see if all the required properties have been supplied |
| 1271 if required: | 1330 if required: |
| 1272 if len(required) > 1: | 1331 if len(required) > 1: |
| 1273 p = 'properties' | 1332 p = 'properties' |
