get actual exception class instead of 'unicode' in the error view
"""abstract action classes for CubicWeb web client:organization: Logilab:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"fromcubicweb.common.appobjectimportAppRsetObjectfromcubicweb.common.registerersimportaction_registererfromcubicweb.common.selectorsimportadd_etype_selector, \searchstate_selector,searchstate_accept_one_selector, \searchstate_accept_one_but_etype_selector_=unicodeclassAction(AppRsetObject):"""abstract action. Handle the .search_states attribute to match request search state. """__registry__='actions'__registerer__=action_registerer__selectors__=(searchstate_selector,)# by default actions don't appear in link search modesearch_states=('normal',)property_defs={'visible':dict(type='Boolean',default=True,help=_('display the action or not')),'order':dict(type='Int',default=99,help=_('display order of the action')),'category':dict(type='String',default='moreactions',vocabulary=('mainactions','moreactions','addrelated','useractions','siteactions','hidden'),help=_('context where this component should be displayed')),}site_wide=True# don't want user to configuration actions epropertiescategory='moreactions'@classmethoddefaccept_rset(cls,req,rset,row,col):user=req.useraction=cls.schema_actionifrowisNone:score=0need_local_check=[]geteschema=cls.schema.eschemaforetypeinrset.column_types(0):accepted=cls.accept(user,etype)ifnotaccepted:return0ifaction:eschema=geteschema(etype)ifnotuser.matching_groups(eschema.get_groups(action)):ifeschema.has_local_role(action):# have to ckeck local rolesneed_local_check.append(eschema)continueelse:# even a local role won't be enoughreturn0score+=acceptedifneed_local_check:# check local role for entities of necessary typesfori,rowinenumerate(rset):ifnotrset.description[i][0]inneed_local_check:continueifnotcls.has_permission(rset.get_entity(i,0),action):return0score+=1returnscorecol=color0etype=rset.description[row][col]score=cls.accept(user,etype)ifscoreandaction:ifnotcls.has_permission(rset.get_entity(row,col),action):return0returnscore@classmethoddefhas_permission(cls,entity,action):"""defined in a separated method to ease overriding (see ModifyAction for instance) """returnentity.has_perm(action)defurl(self):"""return the url associated with this action"""raiseNotImplementedErrordefhtml_class(self):ifself.req.selected(self.url()):return'selected'ifself.category:return'box'+self.category.capitalize()classUnregisteredAction(Action):"""non registered action used to build boxes. Unless you set them explicitly, .vreg and .schema attributes at least are None. """category=Noneid=Nonedef__init__(self,req,rset,title,path,**kwargs):Action.__init__(self,req,rset)self.title=req._(title)self._path=pathself.__dict__.update(kwargs)defurl(self):returnself._pathclassAddEntityAction(Action):"""link to the entity creation form. Concrete class must set .etype and may override .vid """__selectors__=(add_etype_selector,searchstate_selector)vid='creation'etype=Nonedefurl(self):returnself.build_url(vid=self.vid,etype=self.etype)classEntityAction(Action):"""an action for an entity. By default entity actions are only displayable on single entity result if accept match. """__selectors__=(searchstate_accept_one_selector,)schema_action=Nonecondition=None@classmethoddefaccept(cls,user,etype):score=super(EntityAction,cls).accept(user,etype)ifnotscore:return0# check if this type of entity has the necessary relationifhasattr(cls,'rtype')andnotcls.relation_possible(etype):return0returnscoreclassLinkToEntityAction(EntityAction):"""base class for actions consisting to create a new object with an initial relation set to an entity. Additionaly to EntityAction behaviour, this class is parametrized using .etype, .rtype and .target attributes to check if the action apply and if the logged user has access to it """etype=Nonertype=Nonetarget=Nonecategory='addrelated'@classmethoddefaccept_rset(cls,req,rset,row,col):entity=rset.get_entity(rowor0,color0)# check if this type of entity has the necessary relationifhasattr(cls,'rtype')andnotcls.relation_possible(entity.e_schema):return0score=cls.accept(req.user,entity.e_schema)ifnotscore:return0ifnotcls.check_perms(req,entity):return0returnscore@classmethoddefcheck_perms(cls,req,entity):ifnotcls.check_rtype_perm(req,entity):returnFalse# XXX document this:# if user can create the relation, suppose it can create the entity# this is because we usually can't check "add" permission before the# entity has actually been created, and schema security should be# defined considering this#if not cls.check_etype_perm(req, entity):# return FalsereturnTrue@classmethoddefcheck_etype_perm(cls,req,entity):eschema=cls.schema.eschema(cls.etype)ifnoteschema.has_perm(req,'add'):#print req.user.login, 'has no add perm on etype', cls.etypereturnFalse#print 'etype perm ok', clsreturnTrue@classmethoddefcheck_rtype_perm(cls,req,entity):rschema=cls.schema.rschema(cls.rtype)# cls.target is telling us if we want to add the subject or object of# the relationifcls.target=='subject':ifnotrschema.has_perm(req,'add',toeid=entity.eid):#print req.user.login, 'has no add perm on subject rel', cls.rtype, 'with', entityreturnFalseelifnotrschema.has_perm(req,'add',fromeid=entity.eid):#print req.user.login, 'has no add perm on object rel', cls.rtype, 'with', entityreturnFalse#print 'rtype perm ok', clsreturnTruedefurl(self):current_entity=self.rset.get_entity(self.rowor0,self.color0)linkto='%s:%s:%s'%(self.rtype,current_entity.eid,self.target)returnself.build_url(vid='creation',etype=self.etype,__linkto=linkto,__redirectpath=current_entity.rest_path(),# should not be url quoted!__redirectvid=self.req.form.get('__redirectvid',''))classLinkToEntityAction2(LinkToEntityAction):"""LinkToEntity action where the action is not usable on the same entity's type as the one refered by the .etype attribute """__selectors__=(searchstate_accept_one_but_etype_selector,)