comparison roundup/cgi/templating.py @ 1079:04b44df7af1d

removed some property name clashes
author Richard Jones <richard@users.sourceforge.net>
date Mon, 09 Sep 2002 05:28:48 +0000
parents 344bad728d10
children 24c9e81fce85
comparison
equal deleted inserted replaced
1078:344bad728d10 1079:04b44df7af1d
185 185
186 class HTMLDatabase: 186 class HTMLDatabase:
187 ''' Return HTMLClasses for valid class fetches 187 ''' Return HTMLClasses for valid class fetches
188 ''' 188 '''
189 def __init__(self, client): 189 def __init__(self, client):
190 self.client = client 190 self._client = client
191
192 # we want config to be exposed
191 self.config = client.db.config 193 self.config = client.db.config
194
192 def __getattr__(self, attr): 195 def __getattr__(self, attr):
193 try: 196 try:
194 self.client.db.getclass(attr) 197 self._client.db.getclass(attr)
195 except KeyError: 198 except KeyError:
196 raise AttributeError, attr 199 raise AttributeError, attr
197 return HTMLClass(self.client, attr) 200 return HTMLClass(self._client, attr)
198 def classes(self): 201 def classes(self):
199 l = self.client.db.classes.keys() 202 l = self._client.db.classes.keys()
200 l.sort() 203 l.sort()
201 return [HTMLClass(self.client, cn) for cn in l] 204 return [HTMLClass(self._client, cn) for cn in l]
202 205
203 class HTMLClass: 206 class HTMLClass:
204 ''' Accesses through a class (either through *class* or *db.<classname>*) 207 ''' Accesses through a class (either through *class* or *db.<classname>*)
205 ''' 208 '''
206 def __init__(self, client, classname): 209 def __init__(self, client, classname):
207 self.client = client 210 self._client = client
208 self.db = client.db 211 self._db = client.db
212
213 # we want classname to be exposed
209 self.classname = classname 214 self.classname = classname
210 if classname is not None: 215 if classname is not None:
211 self.klass = self.db.getclass(self.classname) 216 self._klass = self._db.getclass(self.classname)
212 self.props = self.klass.getprops() 217 self._props = self._klass.getprops()
213 218
214 def __repr__(self): 219 def __repr__(self):
215 return '<HTMLClass(0x%x) %s>'%(id(self), self.classname) 220 return '<HTMLClass(0x%x) %s>'%(id(self), self.classname)
216 221
217 def __getitem__(self, item): 222 def __getitem__(self, item):
222 # we don't exist 227 # we don't exist
223 if item == 'id': 228 if item == 'id':
224 return None 229 return None
225 if item == 'creator': 230 if item == 'creator':
226 # but we will be created by this user... 231 # but we will be created by this user...
227 return HTMLUser(self.client, 'user', self.client.userid) 232 return HTMLUser(self._client, 'user', self._client.userid)
228 233
229 # get the property 234 # get the property
230 prop = self.props[item] 235 prop = self._props[item]
231 236
232 # look up the correct HTMLProperty class 237 # look up the correct HTMLProperty class
233 for klass, htmlklass in propclasses: 238 for klass, htmlklass in propclasses:
234 if isinstance(prop, hyperdb.Multilink): 239 if isinstance(prop, hyperdb.Multilink):
235 value = [] 240 value = []
236 else: 241 else:
237 value = None 242 value = None
238 if isinstance(prop, klass): 243 if isinstance(prop, klass):
239 return htmlklass(self.client, '', prop, item, value) 244 return htmlklass(self._client, '', prop, item, value)
240 245
241 # no good 246 # no good
242 raise KeyError, item 247 raise KeyError, item
243 248
244 def __getattr__(self, attr): 249 def __getattr__(self, attr):
250 255
251 def properties(self): 256 def properties(self):
252 ''' Return HTMLProperty for all props 257 ''' Return HTMLProperty for all props
253 ''' 258 '''
254 l = [] 259 l = []
255 for name, prop in self.props.items(): 260 for name, prop in self._props.items():
256 for klass, htmlklass in propclasses: 261 for klass, htmlklass in propclasses:
257 if isinstance(prop, hyperdb.Multilink): 262 if isinstance(prop, hyperdb.Multilink):
258 value = [] 263 value = []
259 else: 264 else:
260 value = None 265 value = None
261 if isinstance(prop, klass): 266 if isinstance(prop, klass):
262 l.append(htmlklass(self.client, '', prop, name, value)) 267 l.append(htmlklass(self._client, '', prop, name, value))
263 return l 268 return l
264 269
265 def list(self): 270 def list(self):
266 if self.classname == 'user': 271 if self.classname == 'user':
267 klass = HTMLUser 272 klass = HTMLUser
268 else: 273 else:
269 klass = HTMLItem 274 klass = HTMLItem
270 l = [klass(self.client, self.classname, x) for x in self.klass.list()] 275 l = [klass(self._client, self.classname, x) for x in self._klass.list()]
271 return l 276 return l
272 277
273 def csv(self): 278 def csv(self):
274 ''' Return the items of this class as a chunk of CSV text. 279 ''' Return the items of this class as a chunk of CSV text.
275 ''' 280 '''
282 287
283 props = self.propnames() 288 props = self.propnames()
284 p = csv.parser() 289 p = csv.parser()
285 s = StringIO.StringIO() 290 s = StringIO.StringIO()
286 s.write(p.join(props) + '\n') 291 s.write(p.join(props) + '\n')
287 for nodeid in self.klass.list(): 292 for nodeid in self._klass.list():
288 l = [] 293 l = []
289 for name in props: 294 for name in props:
290 value = self.klass.get(nodeid, name) 295 value = self._klass.get(nodeid, name)
291 if value is None: 296 if value is None:
292 l.append('') 297 l.append('')
293 elif isinstance(value, type([])): 298 elif isinstance(value, type([])):
294 l.append(':'.join(map(str, value))) 299 l.append(':'.join(map(str, value)))
295 else: 300 else:
296 l.append(str(self.klass.get(nodeid, name))) 301 l.append(str(self._klass.get(nodeid, name)))
297 s.write(p.join(l) + '\n') 302 s.write(p.join(l) + '\n')
298 return s.getvalue() 303 return s.getvalue()
299 304
300 def propnames(self): 305 def propnames(self):
301 ''' Return the list of the names of the properties of this class. 306 ''' Return the list of the names of the properties of this class.
302 ''' 307 '''
303 idlessprops = self.klass.getprops(protected=0).keys() 308 idlessprops = self._klass.getprops(protected=0).keys()
304 idlessprops.sort() 309 idlessprops.sort()
305 return ['id'] + idlessprops 310 return ['id'] + idlessprops
306 311
307 def filter(self, request=None): 312 def filter(self, request=None):
308 ''' Return a list of items from this class, filtered and sorted 313 ''' Return a list of items from this class, filtered and sorted
314 group = request.group 319 group = request.group
315 if self.classname == 'user': 320 if self.classname == 'user':
316 klass = HTMLUser 321 klass = HTMLUser
317 else: 322 else:
318 klass = HTMLItem 323 klass = HTMLItem
319 l = [klass(self.client, self.classname, x) 324 l = [klass(self._client, self.classname, x)
320 for x in self.klass.filter(None, filterspec, sort, group)] 325 for x in self._klass.filter(None, filterspec, sort, group)]
321 return l 326 return l
322 327
323 def classhelp(self, properties, label='?', width='400', height='400'): 328 def classhelp(self, properties, label='?', width='400', height='400'):
324 '''pop up a javascript window with class help 329 '''pop up a javascript window with class help
325 330
346 351
347 def renderWith(self, name, **kwargs): 352 def renderWith(self, name, **kwargs):
348 ''' Render this class with the given template. 353 ''' Render this class with the given template.
349 ''' 354 '''
350 # create a new request and override the specified args 355 # create a new request and override the specified args
351 req = HTMLRequest(self.client) 356 req = HTMLRequest(self._client)
352 req.classname = self.classname 357 req.classname = self.classname
353 req.update(kwargs) 358 req.update(kwargs)
354 359
355 # new template, using the specified classname and request 360 # new template, using the specified classname and request
356 pt = getTemplate(self.db.config.TEMPLATES, self.classname, name) 361 pt = getTemplate(self._db.config.TEMPLATES, self.classname, name)
357 362
358 # XXX handle PT rendering errors here nicely 363 # XXX handle PT rendering errors here nicely
359 try: 364 try:
360 # use our fabricated request 365 # use our fabricated request
361 return pt.render(self.client, self.classname, req) 366 return pt.render(self._client, self.classname, req)
362 except PageTemplate.PTRuntimeError, message: 367 except PageTemplate.PTRuntimeError, message:
363 return '<strong>%s</strong><ol>%s</ol>'%(message, 368 return '<strong>%s</strong><ol>%s</ol>'%(message,
364 cgi.escape('<li>'.join(pt._v_errors))) 369 cgi.escape('<li>'.join(pt._v_errors)))
365 370
366 class HTMLItem: 371 class HTMLItem:
367 ''' Accesses through an *item* 372 ''' Accesses through an *item*
368 ''' 373 '''
369 def __init__(self, client, classname, nodeid): 374 def __init__(self, client, classname, nodeid):
370 self.client = client 375 self._client = client
371 self.db = client.db 376 self._db = client.db
372 self.classname = classname 377 self._classname = classname
373 self.nodeid = nodeid 378 self._nodeid = nodeid
374 self.klass = self.db.getclass(classname) 379 self._klass = self._db.getclass(classname)
375 self.props = self.klass.getprops() 380 self._props = self._klass.getprops()
376 381
377 def __repr__(self): 382 def __repr__(self):
378 return '<HTMLItem(0x%x) %s %s>'%(id(self), self.classname, self.nodeid) 383 return '<HTMLItem(0x%x) %s %s>'%(id(self), self._classname,
384 self._nodeid)
379 385
380 def __getitem__(self, item): 386 def __getitem__(self, item):
381 ''' return an HTMLProperty instance 387 ''' return an HTMLProperty instance
382 ''' 388 '''
383 #print 'getitem', (self, item) 389 #print 'getitem', (self, item)
384 if item == 'id': 390 if item == 'id':
385 return self.nodeid 391 return self._nodeid
386 392
387 # get the property 393 # get the property
388 prop = self.props[item] 394 prop = self._props[item]
389 395
390 # get the value, handling missing values 396 # get the value, handling missing values
391 value = self.klass.get(self.nodeid, item, None) 397 value = self._klass.get(self._nodeid, item, None)
392 if value is None: 398 if value is None:
393 if isinstance(self.props[item], hyperdb.Multilink): 399 if isinstance(self._props[item], hyperdb.Multilink):
394 value = [] 400 value = []
395 401
396 # look up the correct HTMLProperty class 402 # look up the correct HTMLProperty class
397 for klass, htmlklass in propclasses: 403 for klass, htmlklass in propclasses:
398 if isinstance(prop, klass): 404 if isinstance(prop, klass):
399 return htmlklass(self.client, self.nodeid, prop, item, value) 405 return htmlklass(self._client, self._nodeid, prop, item, value)
400 406
401 raise KeyErorr, item 407 raise KeyErorr, item
402 408
403 def __getattr__(self, attr): 409 def __getattr__(self, attr):
404 ''' convenience access to properties ''' 410 ''' convenience access to properties '''
423 _('<th>User</th>'), 429 _('<th>User</th>'),
424 _('<th>Action</th>'), 430 _('<th>Action</th>'),
425 _('<th>Args</th>'), 431 _('<th>Args</th>'),
426 '</tr>'] 432 '</tr>']
427 comments = {} 433 comments = {}
428 history = self.klass.history(self.nodeid) 434 history = self._klass.history(self._nodeid)
429 history.sort() 435 history.sort()
430 if direction == 'descending': 436 if direction == 'descending':
431 history.reverse() 437 history.reverse()
432 for id, evt_date, user, action, args in history: 438 for id, evt_date, user, action, args in history:
433 date_s = str(evt_date).replace("."," ") 439 date_s = str(evt_date).replace("."," ")
452 cell = [] 458 cell = []
453 for k in args.keys(): 459 for k in args.keys():
454 # try to get the relevant property and treat it 460 # try to get the relevant property and treat it
455 # specially 461 # specially
456 try: 462 try:
457 prop = self.props[k] 463 prop = self._props[k]
458 except KeyError: 464 except KeyError:
459 prop = None 465 prop = None
460 if prop is not None: 466 if prop is not None:
461 if args[k] and (isinstance(prop, hyperdb.Multilink) or 467 if args[k] and (isinstance(prop, hyperdb.Multilink) or
462 isinstance(prop, hyperdb.Link)): 468 isinstance(prop, hyperdb.Link)):
463 # figure what the link class is 469 # figure what the link class is
464 classname = prop.classname 470 classname = prop.classname
465 try: 471 try:
466 linkcl = self.db.getclass(classname) 472 linkcl = self._db.getclass(classname)
467 except KeyError: 473 except KeyError:
468 labelprop = None 474 labelprop = None
469 comments[classname] = _('''The linked class 475 comments[classname] = _('''The linked class
470 %(classname)s no longer exists''')%locals() 476 %(classname)s no longer exists''')%locals()
471 labelprop = linkcl.labelprop(1) 477 labelprop = linkcl.labelprop(1)
472 hrefable = os.path.exists( 478 hrefable = os.path.exists(
473 os.path.join(self.db.config.TEMPLATES, 479 os.path.join(self._db.config.TEMPLATES,
474 classname+'.item')) 480 classname+'.item'))
475 481
476 if isinstance(prop, hyperdb.Multilink) and \ 482 if isinstance(prop, hyperdb.Multilink) and \
477 len(args[k]) > 0: 483 len(args[k]) > 0:
478 ml = [] 484 ml = []
565 class HTMLUser(HTMLItem): 571 class HTMLUser(HTMLItem):
566 ''' Accesses through the *user* (a special case of item) 572 ''' Accesses through the *user* (a special case of item)
567 ''' 573 '''
568 def __init__(self, client, classname, nodeid): 574 def __init__(self, client, classname, nodeid):
569 HTMLItem.__init__(self, client, 'user', nodeid) 575 HTMLItem.__init__(self, client, 'user', nodeid)
570 self.default_classname = client.classname 576 self._default_classname = client.classname
571 577
572 # used for security checks 578 # used for security checks
573 self.security = client.db.security 579 self._security = client.db.security
574 _marker = [] 580 _marker = []
575 def hasPermission(self, role, classname=_marker): 581 def hasPermission(self, role, classname=_marker):
576 ''' Determine if the user has the Role. 582 ''' Determine if the user has the Role.
577 583
578 The class being tested defaults to the template's class, but may 584 The class being tested defaults to the template's class, but may
579 be overidden for this test by suppling an alternate classname. 585 be overidden for this test by suppling an alternate classname.
580 ''' 586 '''
581 if classname is self._marker: 587 if classname is self._marker:
582 classname = self.default_classname 588 classname = self._default_classname
583 return self.security.hasPermission(role, self.nodeid, classname) 589 return self._security.hasPermission(role, self._nodeid, classname)
584 590
585 class HTMLProperty: 591 class HTMLProperty:
586 ''' String, Number, Date, Interval HTMLProperty 592 ''' String, Number, Date, Interval HTMLProperty
587 593
588 A wrapper object which may be stringified for the plain() behaviour. 594 A wrapper object which may be stringified for the plain() behaviour.
589 ''' 595 '''
590 def __init__(self, client, nodeid, prop, name, value): 596 def __init__(self, client, nodeid, prop, name, value):
591 self.client = client 597 self._client = client
592 self.db = client.db 598 self._db = client.db
593 self.nodeid = nodeid 599 self._nodeid = nodeid
594 self.prop = prop 600 self._prop = prop
595 self.name = name 601 self._name = name
596 self.value = value 602 self._value = value
597 def __repr__(self): 603 def __repr__(self):
598 return '<HTMLProperty(0x%x) %s %r %r>'%(id(self), self.name, self.prop, self.value) 604 return '<HTMLProperty(0x%x) %s %r %r>'%(id(self), self._name, self._prop, self._value)
599 def __str__(self): 605 def __str__(self):
600 return self.plain() 606 return self.plain()
601 def __cmp__(self, other): 607 def __cmp__(self, other):
602 if isinstance(other, HTMLProperty): 608 if isinstance(other, HTMLProperty):
603 return cmp(self.value, other.value) 609 return cmp(self._value, other._value)
604 return cmp(self.value, other) 610 return cmp(self._value, other)
605 611
606 class StringHTMLProperty(HTMLProperty): 612 class StringHTMLProperty(HTMLProperty):
607 def plain(self, escape=0): 613 def plain(self, escape=0):
608 if self.value is None: 614 if self._value is None:
609 return '' 615 return ''
610 if escape: 616 if escape:
611 return cgi.escape(str(self.value)) 617 return cgi.escape(str(self._value))
612 return str(self.value) 618 return str(self._value)
613 619
614 def stext(self, escape=0): 620 def stext(self, escape=0):
615 s = self.plain(escape=escape) 621 s = self.plain(escape=escape)
616 if not StructuredText: 622 if not StructuredText:
617 return s 623 return s
618 return StructuredText(s,level=1,header=0) 624 return StructuredText(s,level=1,header=0)
619 625
620 def field(self, size = 30): 626 def field(self, size = 30):
621 if self.value is None: 627 if self._value is None:
622 value = '' 628 value = ''
623 else: 629 else:
624 value = cgi.escape(str(self.value)) 630 value = cgi.escape(str(self._value))
625 value = '&quot;'.join(value.split('"')) 631 value = '&quot;'.join(value.split('"'))
626 return '<input name="%s" value="%s" size="%s">'%(self.name, value, size) 632 return '<input name="%s" value="%s" size="%s">'%(self._name, value, size)
627 633
628 def multiline(self, escape=0, rows=5, cols=40): 634 def multiline(self, escape=0, rows=5, cols=40):
629 if self.value is None: 635 if self._value is None:
630 value = '' 636 value = ''
631 else: 637 else:
632 value = cgi.escape(str(self.value)) 638 value = cgi.escape(str(self._value))
633 value = '&quot;'.join(value.split('"')) 639 value = '&quot;'.join(value.split('"'))
634 return '<textarea name="%s" rows="%s" cols="%s">%s</textarea>'%( 640 return '<textarea name="%s" rows="%s" cols="%s">%s</textarea>'%(
635 self.name, rows, cols, value) 641 self._name, rows, cols, value)
636 642
637 def email(self, escape=1): 643 def email(self, escape=1):
638 ''' fudge email ''' 644 ''' fudge email '''
639 if self.value is None: value = '' 645 if self.value is None: value = ''
640 else: value = str(self.value) 646 else: value = str(self._value)
641 value = value.replace('@', ' at ') 647 value = value.replace('@', ' at ')
642 value = value.replace('.', ' ') 648 value = value.replace('.', ' ')
643 if escape: 649 if escape:
644 value = cgi.escape(value) 650 value = cgi.escape(value)
645 return value 651 return value
646 652
647 class PasswordHTMLProperty(HTMLProperty): 653 class PasswordHTMLProperty(HTMLProperty):
648 def plain(self): 654 def plain(self):
649 if self.value is None: 655 if self._value is None:
650 return '' 656 return ''
651 return _('*encrypted*') 657 return _('*encrypted*')
652 658
653 def field(self, size = 30): 659 def field(self, size = 30):
654 return '<input type="password" name="%s" size="%s">'%(self.name, size) 660 return '<input type="password" name="%s" size="%s">'%(self._name, size)
655 661
656 class NumberHTMLProperty(HTMLProperty): 662 class NumberHTMLProperty(HTMLProperty):
657 def plain(self): 663 def plain(self):
658 return str(self.value) 664 return str(self._value)
659 665
660 def field(self, size = 30): 666 def field(self, size = 30):
661 if self.value is None: 667 if self._value is None:
662 value = '' 668 value = ''
663 else: 669 else:
664 value = cgi.escape(str(self.value)) 670 value = cgi.escape(str(self._value))
665 value = '&quot;'.join(value.split('"')) 671 value = '&quot;'.join(value.split('"'))
666 return '<input name="%s" value="%s" size="%s">'%(self.name, value, size) 672 return '<input name="%s" value="%s" size="%s">'%(self._name, value, size)
667 673
668 class BooleanHTMLProperty(HTMLProperty): 674 class BooleanHTMLProperty(HTMLProperty):
669 def plain(self): 675 def plain(self):
670 if self.value is None: 676 if self.value is None:
671 return '' 677 return ''
672 return self.value and "Yes" or "No" 678 return self._value and "Yes" or "No"
673 679
674 def field(self): 680 def field(self):
675 checked = self.value and "checked" or "" 681 checked = self._value and "checked" or ""
676 s = '<input type="radio" name="%s" value="yes" %s>Yes'%(self.name, 682 s = '<input type="radio" name="%s" value="yes" %s>Yes'%(self._name,
677 checked) 683 checked)
678 if checked: 684 if checked:
679 checked = "" 685 checked = ""
680 else: 686 else:
681 checked = "checked" 687 checked = "checked"
682 s += '<input type="radio" name="%s" value="no" %s>No'%(self.name, 688 s += '<input type="radio" name="%s" value="no" %s>No'%(self._name,
683 checked) 689 checked)
684 return s 690 return s
685 691
686 class DateHTMLProperty(HTMLProperty): 692 class DateHTMLProperty(HTMLProperty):
687 def plain(self): 693 def plain(self):
688 if self.value is None: 694 if self._value is None:
689 return '' 695 return ''
690 return str(self.value) 696 return str(self._value)
691 697
692 def field(self, size = 30): 698 def field(self, size = 30):
693 if self.value is None: 699 if self._value is None:
694 value = '' 700 value = ''
695 else: 701 else:
696 value = cgi.escape(str(self.value)) 702 value = cgi.escape(str(self._value))
697 value = '&quot;'.join(value.split('"')) 703 value = '&quot;'.join(value.split('"'))
698 return '<input name="%s" value="%s" size="%s">'%(self.name, value, size) 704 return '<input name="%s" value="%s" size="%s">'%(self._name, value, size)
699 705
700 def reldate(self, pretty=1): 706 def reldate(self, pretty=1):
701 if not self.value: 707 if not self._value:
702 return '' 708 return ''
703 709
704 # figure the interval 710 # figure the interval
705 interval = date.Date('.') - self.value 711 interval = date.Date('.') - self._value
706 if pretty: 712 if pretty:
707 return interval.pretty() 713 return interval.pretty()
708 return str(interval) 714 return str(interval)
709 715
710 class IntervalHTMLProperty(HTMLProperty): 716 class IntervalHTMLProperty(HTMLProperty):
711 def plain(self): 717 def plain(self):
712 if self.value is None: 718 if self._value is None:
713 return '' 719 return ''
714 return str(self.value) 720 return str(self._value)
715 721
716 def pretty(self): 722 def pretty(self):
717 return self.value.pretty() 723 return self._value.pretty()
718 724
719 def field(self, size = 30): 725 def field(self, size = 30):
720 if self.value is None: 726 if self._value is None:
721 value = '' 727 value = ''
722 else: 728 else:
723 value = cgi.escape(str(self.value)) 729 value = cgi.escape(str(self._value))
724 value = '&quot;'.join(value.split('"')) 730 value = '&quot;'.join(value.split('"'))
725 return '<input name="%s" value="%s" size="%s">'%(self.name, value, size) 731 return '<input name="%s" value="%s" size="%s">'%(self._name, value, size)
726 732
727 class LinkHTMLProperty(HTMLProperty): 733 class LinkHTMLProperty(HTMLProperty):
728 ''' Link HTMLProperty 734 ''' Link HTMLProperty
729 Include the above as well as being able to access the class 735 Include the above as well as being able to access the class
730 information. Stringifying the object itself results in the value 736 information. Stringifying the object itself results in the value
734 entry identified by the assignedto property on item, and then the 740 entry identified by the assignedto property on item, and then the
735 name property of that user) 741 name property of that user)
736 ''' 742 '''
737 def __getattr__(self, attr): 743 def __getattr__(self, attr):
738 ''' return a new HTMLItem ''' 744 ''' return a new HTMLItem '''
739 #print 'getattr', (self, attr, self.value) 745 #print 'getattr', (self, attr, self._value)
740 if not self.value: 746 if not self._value:
741 raise AttributeError, "Can't access missing value" 747 raise AttributeError, "Can't access missing value"
742 if self.prop.classname == 'user': 748 if self._prop.classname == 'user':
743 klass = HTMLItem 749 klass = HTMLItem
744 else: 750 else:
745 klass = HTMLUser 751 klass = HTMLUser
746 i = klass(self.client, self.prop.classname, self.value) 752 i = klass(self._client, self._prop.classname, self._value)
747 return getattr(i, attr) 753 return getattr(i, attr)
748 754
749 def plain(self, escape=0): 755 def plain(self, escape=0):
750 if self.value is None: 756 if self._value is None:
751 return _('[unselected]') 757 return _('[unselected]')
752 linkcl = self.db.classes[self.prop.classname] 758 linkcl = self._db.classes[self._prop.classname]
753 k = linkcl.labelprop(1) 759 k = linkcl.labelprop(1)
754 value = str(linkcl.get(self.value, k)) 760 value = str(linkcl.get(self._value, k))
755 if escape: 761 if escape:
756 value = cgi.escape(value) 762 value = cgi.escape(value)
757 return value 763 return value
758 764
759 def field(self): 765 def field(self):
760 linkcl = self.db.getclass(self.prop.classname) 766 linkcl = self._db.getclass(self._prop.classname)
761 if linkcl.getprops().has_key('order'): 767 if linkcl.getprops().has_key('order'):
762 sort_on = 'order' 768 sort_on = 'order'
763 else: 769 else:
764 sort_on = linkcl.labelprop() 770 sort_on = linkcl.labelprop()
765 options = linkcl.filter(None, {}, [sort_on], []) 771 options = linkcl.filter(None, {}, [sort_on], [])
775 option = linkcl.get(optionid, k) 781 option = linkcl.get(optionid, k)
776 s = '' 782 s = ''
777 if optionid == value: 783 if optionid == value:
778 s = 'selected ' 784 s = 'selected '
779 if showid: 785 if showid:
780 lab = '%s%s: %s'%(self.prop.classname, optionid, option) 786 lab = '%s%s: %s'%(self._prop.classname, optionid, option)
781 else: 787 else:
782 lab = option 788 lab = option
783 if size is not None and len(lab) > size: 789 if size is not None and len(lab) > size:
784 lab = lab[:size-3] + '...' 790 lab = lab[:size-3] + '...'
785 lab = cgi.escape(lab) 791 lab = cgi.escape(lab)
786 l.append('<option %svalue="%s">%s</option>'%(s, optionid, lab)) 792 l.append('<option %svalue="%s">%s</option>'%(s, optionid, lab))
787 l.append('</select>') 793 l.append('</select>')
788 return '\n'.join(l) 794 return '\n'.join(l)
789 795
790 def download(self, showid=0): 796 def download(self, showid=0):
791 linkname = self.prop.classname 797 linkname = self._prop.classname
792 linkcl = self.db.getclass(linkname) 798 linkcl = self._db.getclass(linkname)
793 k = linkcl.labelprop(1) 799 k = linkcl.labelprop(1)
794 linkvalue = cgi.escape(str(linkcl.get(self.value, k))) 800 linkvalue = cgi.escape(str(linkcl.get(self._value, k)))
795 if showid: 801 if showid:
796 label = value 802 label = value
797 title = ' title="%s"'%linkvalue 803 title = ' title="%s"'%linkvalue
798 # note ... this should be urllib.quote(linkcl.get(value, k)) 804 # note ... this should be urllib.quote(linkcl.get(value, k))
799 else: 805 else:
800 label = linkvalue 806 label = linkvalue
801 title = '' 807 title = ''
802 return '<a href="%s%s/%s"%s>%s</a>'%(linkname, self.value, 808 return '<a href="%s%s/%s"%s>%s</a>'%(linkname, self._value,
803 linkvalue, title, label) 809 linkvalue, title, label)
804 810
805 def menu(self, size=None, height=None, showid=0, additional=[], 811 def menu(self, size=None, height=None, showid=0, additional=[],
806 **conditions): 812 **conditions):
807 value = self.value 813 value = self._value
808 814
809 # sort function 815 # sort function
810 sortfunc = make_sort_function(self.db, self.prop.classname) 816 sortfunc = make_sort_function(self._db, self._prop.classname)
811 817
812 # force the value to be a single choice 818 # force the value to be a single choice
813 if isinstance(value, type('')): 819 if isinstance(value, type('')):
814 value = value[0] 820 value = value[0]
815 linkcl = self.db.getclass(self.prop.classname) 821 linkcl = self._db.getclass(self._prop.classname)
816 l = ['<select name="%s">'%self.name] 822 l = ['<select name="%s">'%self._name]
817 k = linkcl.labelprop(1) 823 k = linkcl.labelprop(1)
818 s = '' 824 s = ''
819 if value is None: 825 if value is None:
820 s = 'selected ' 826 s = 'selected '
821 l.append(_('<option %svalue="-1">- no selection -</option>')%s) 827 l.append(_('<option %svalue="-1">- no selection -</option>')%s)
828 option = linkcl.get(optionid, k) 834 option = linkcl.get(optionid, k)
829 s = '' 835 s = ''
830 if value in [optionid, option]: 836 if value in [optionid, option]:
831 s = 'selected ' 837 s = 'selected '
832 if showid: 838 if showid:
833 lab = '%s%s: %s'%(self.prop.classname, optionid, option) 839 lab = '%s%s: %s'%(self._prop.classname, optionid, option)
834 else: 840 else:
835 lab = option 841 lab = option
836 if size is not None and len(lab) > size: 842 if size is not None and len(lab) > size:
837 lab = lab[:size-3] + '...' 843 lab = lab[:size-3] + '...'
838 if additional: 844 if additional:
853 Also be iterable, returning a wrapper object like the Link case for 859 Also be iterable, returning a wrapper object like the Link case for
854 each entry in the multilink. 860 each entry in the multilink.
855 ''' 861 '''
856 def __len__(self): 862 def __len__(self):
857 ''' length of the multilink ''' 863 ''' length of the multilink '''
858 return len(self.value) 864 return len(self._value)
859 865
860 def __getattr__(self, attr): 866 def __getattr__(self, attr):
861 ''' no extended attribute accesses make sense here ''' 867 ''' no extended attribute accesses make sense here '''
862 raise AttributeError, attr 868 raise AttributeError, attr
863 869
864 def __getitem__(self, num): 870 def __getitem__(self, num):
865 ''' iterate and return a new HTMLItem 871 ''' iterate and return a new HTMLItem
866 ''' 872 '''
867 #print 'getitem', (self, num) 873 #print 'getitem', (self, num)
868 value = self.value[num] 874 value = self._value[num]
869 if self.prop.classname == 'user': 875 if self._prop.classname == 'user':
870 klass = HTMLUser 876 klass = HTMLUser
871 else: 877 else:
872 klass = HTMLItem 878 klass = HTMLItem
873 return klass(self.client, self.prop.classname, value) 879 return klass(self._client, self._prop.classname, value)
874 880
875 def reverse(self): 881 def reverse(self):
876 ''' return the list in reverse order 882 ''' return the list in reverse order
877 ''' 883 '''
878 l = self.value[:] 884 l = self._value[:]
879 l.reverse() 885 l.reverse()
880 if self.prop.classname == 'user': 886 if self._prop.classname == 'user':
881 klass = HTMLUser 887 klass = HTMLUser
882 else: 888 else:
883 klass = HTMLItem 889 klass = HTMLItem
884 return [klass(self.client, self.prop.classname, value) for value in l] 890 return [klass(self._client, self._prop.classname, value) for value in l]
885 891
886 def plain(self, escape=0): 892 def plain(self, escape=0):
887 linkcl = self.db.classes[self.prop.classname] 893 linkcl = self._db.classes[self._prop.classname]
888 k = linkcl.labelprop(1) 894 k = linkcl.labelprop(1)
889 labels = [] 895 labels = []
890 for v in self.value: 896 for v in self._value:
891 labels.append(linkcl.get(v, k)) 897 labels.append(linkcl.get(v, k))
892 value = ', '.join(labels) 898 value = ', '.join(labels)
893 if escape: 899 if escape:
894 value = cgi.escape(value) 900 value = cgi.escape(value)
895 return value 901 return value
896 902
897 def field(self, size=30, showid=0): 903 def field(self, size=30, showid=0):
898 sortfunc = make_sort_function(self.db, self.prop.classname) 904 sortfunc = make_sort_function(self._db, self._prop.classname)
899 linkcl = self.db.getclass(self.prop.classname) 905 linkcl = self._db.getclass(self._prop.classname)
900 value = self.value[:] 906 value = self._value[:]
901 if value: 907 if value:
902 value.sort(sortfunc) 908 value.sort(sortfunc)
903 # map the id to the label property 909 # map the id to the label property
904 if not showid: 910 if not showid:
905 k = linkcl.labelprop(1) 911 k = linkcl.labelprop(1)
906 value = [linkcl.get(v, k) for v in value] 912 value = [linkcl.get(v, k) for v in value]
907 value = cgi.escape(','.join(value)) 913 value = cgi.escape(','.join(value))
908 return '<input name="%s" size="%s" value="%s">'%(self.name, size, value) 914 return '<input name="%s" size="%s" value="%s">'%(self._name, size, value)
909 915
910 def menu(self, size=None, height=None, showid=0, additional=[], 916 def menu(self, size=None, height=None, showid=0, additional=[],
911 **conditions): 917 **conditions):
912 value = self.value 918 value = self._value
913 919
914 # sort function 920 # sort function
915 sortfunc = make_sort_function(self.db, self.prop.classname) 921 sortfunc = make_sort_function(self._db, self._prop.classname)
916 922
917 linkcl = self.db.getclass(self.prop.classname) 923 linkcl = self._db.getclass(self._prop.classname)
918 if linkcl.getprops().has_key('order'): 924 if linkcl.getprops().has_key('order'):
919 sort_on = ('+', 'order') 925 sort_on = ('+', 'order')
920 else: 926 else:
921 sort_on = ('+', linkcl.labelprop()) 927 sort_on = ('+', linkcl.labelprop())
922 options = linkcl.filter(None, conditions, sort_on, (None,None)) 928 options = linkcl.filter(None, conditions, sort_on, (None,None))
923 height = height or min(len(options), 7) 929 height = height or min(len(options), 7)
924 l = ['<select multiple name="%s" size="%s">'%(self.name, height)] 930 l = ['<select multiple name="%s" size="%s">'%(self._name, height)]
925 k = linkcl.labelprop(1) 931 k = linkcl.labelprop(1)
926 for optionid in options: 932 for optionid in options:
927 option = linkcl.get(optionid, k) 933 option = linkcl.get(optionid, k)
928 s = '' 934 s = ''
929 if optionid in value or option in value: 935 if optionid in value or option in value:
930 s = 'selected ' 936 s = 'selected '
931 if showid: 937 if showid:
932 lab = '%s%s: %s'%(self.prop.classname, optionid, option) 938 lab = '%s%s: %s'%(self._prop.classname, optionid, option)
933 else: 939 else:
934 lab = option 940 lab = option
935 if size is not None and len(lab) > size: 941 if size is not None and len(lab) > size:
936 lab = lab[:size-3] + '...' 942 lab = lab[:size-3] + '...'
937 if additional: 943 if additional:

Roundup Issue Tracker: http://roundup-tracker.org/