[toward py3k] rewrite dict.keys() and dict.values() (part of #2711624)
Python 3K will only expose iterators.
http://docs.python.org/3.0/whatsnew/3.0.html#views-and-iterators-instead-of-lists
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb is free software: you can redistribute it and/or modify it under the# terms of the GNU Lesser General Public License as published by the Free# Software Foundation, either version 2.1 of the License, or (at your option)# any later version.## CubicWeb is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more# details.## You should have received a copy of the GNU Lesser General Public License along# with CubicWeb. If not, see <http://www.gnu.org/licenses/>."""This module (``cubicweb.web.views.uicfg``) regroups a set of structures that may beused to configure various options of the generated web interface.To configure the interface generation, we use ``RelationTag`` objects.Index view configuration````````````````````````:indexview_etype_section: entity type category in the index/manage page. May be one of: * ``application`` * ``system`` * ``schema`` * ``subobject`` (not displayed by default) By default only entities on the ``application`` category are shown... sourcecode:: python from cubicweb.web.views import uicfg # force hiding uicfg.indexview_etype_section['HideMe'] = 'subobject' # force display uicfg.indexview_etype_section['ShowMe'] = 'application'Actions box configuration`````````````````````````:actionbox_appearsin_addmenu: simple boolean relation tags used to control the "add entity" submenu. Relations whose rtag is True will appears, other won't... sourcecode:: python # Adds all subjects of the entry_of relation in the add menu of the ``Blog`` # primary view uicfg.actionbox_appearsin_addmenu.tag_object_of(('*', 'entry_of', 'Blog'), True)"""__docformat__="restructuredtext en"fromwarningsimportwarnfromlogilab.common.compatimportanyfromcubicwebimportneg_rolefromcubicweb.rtagsimport(RelationTags,RelationTagsBool,RelationTagsSet,RelationTagsDict,NoTargetRelationTagsDict,_ensure_str_key)fromcubicweb.schemaimportMETA_RTYPES,INTERNAL_TYPES,WORKFLOW_TYPES# primary view configuration ##################################################classPrimaryViewSectionRelationTags(RelationTags):"""primary view section configuration"""__regid__='primaryview_section'_allowed_values=frozenset(('attributes','relations','sideboxes','hidden'))def_init(self,sschema,rschema,oschema,role):ifself.get(sschema,rschema,oschema,role)isNone:rdef=rschema.rdef(sschema,oschema)ifrschema.final:ifrschema.metaorsschema.is_metadata(rschema) \oroschema.typein('Password','Bytes'):section='hidden'else:section='attributes'else:ifrdef.role_cardinality(role)in'1+':section='attributes'elifrdef.composite==neg_role(role):section='relations'else:section='sideboxes'self.tag_relation((sschema,rschema,oschema,role),section)primaryview_section=PrimaryViewSectionRelationTags()classDisplayCtrlRelationTags(NoTargetRelationTagsDict):"""primary view display controller configuration"""__regid__='primaryview_display_ctrl'def__init__(self,*args,**kwargs):super(DisplayCtrlRelationTags,self).__init__(*args,**kwargs)self.counter=0def_init(self,sschema,rschema,oschema,role):ifrole=='subject':oschema='*'else:sschema='*'self.counter+=1self.setdefault((sschema,rschema,oschema,role),'order',self.counter)primaryview_display_ctrl=DisplayCtrlRelationTags()# index view configuration ##################################################### entity type section in the index/manage page. May be one of# * 'application'# * 'system'# * 'schema'# * 'hidden'# * 'subobject' (not displayed by default)classInitializableDict(dict):# XXX not a rtag. Turn into an appobject?def__init__(self,*args,**kwargs):super(InitializableDict,self).__init__(*args,**kwargs)self.__defaults=dict(self)definit(self,schema,check=True):self.update(self.__defaults)foreschemainschema.entities():ifeschema.final:continueifeschema.schema_entity():self.setdefault(eschema,'schema')elifeschemainINTERNAL_TYPESoreschemainWORKFLOW_TYPES:self.setdefault(eschema,'system')elifeschema.is_subobject(strict=True):self.setdefault(eschema,'subobject')else:self.setdefault(eschema,'application')indexview_etype_section=InitializableDict(EmailAddress='subobject',Bookmark='system',# entity types in the 'system' table by default (managers only)CWUser='system',CWGroup='system',)# autoform.AutomaticEntityForm configuration ##################################def_formsections_as_dict(formsections):result={}forformsectioninformsections:formtype,section=formsection.split('_',1)result[formtype]=sectionreturnresultdef_card_and_comp(sschema,rschema,oschema,role):rdef=rschema.rdef(sschema,oschema)ifrole=='subject':card=rdef.cardinality[0]composed=notrschema.finalandrdef.composite=='object'else:card=rdef.cardinality[1]composed=notrschema.finalandrdef.composite=='subject'returncard,composedclassAutoformSectionRelationTags(RelationTagsSet):"""autoform relations'section"""__regid__='autoform_section'_allowed_form_types=('main','inlined','muledit')_allowed_values={'main':('attributes','inlined','relations','metadata','hidden'),'inlined':('attributes','inlined','hidden'),'muledit':('attributes','hidden'),}definit(self,schema,check=True):super(AutoformSectionRelationTags,self).init(schema,check)self.apply(schema,self._initfunc_step2)def_init(self,sschema,rschema,oschema,role):formsections=self.init_get(sschema,rschema,oschema,role)ifformsectionsisNone:formsections=self.tag_container_cls()ifnotany(tag.startswith('inlined')fortaginformsections):ifnotrschema.final:negsects=self.init_get(sschema,rschema,oschema,neg_role(role))if'main_inlined'innegsects:formsections.add('inlined_hidden')key=_ensure_str_key((sschema,rschema,oschema,role))self._tagdefs[key]=formsectionsdef_initfunc_step2(self,sschema,rschema,oschema,role):formsections=self.get(sschema,rschema,oschema,role)sectdict=_formsections_as_dict(formsections)ifrschemainMETA_RTYPES:sectdict.setdefault('main','hidden')sectdict.setdefault('muledit','hidden')sectdict.setdefault('inlined','hidden')elifrole=='subject'andrschemainsschema.meta_attributes():# meta attribute, usually embeded by the described attribute's field# (eg RichTextField, FileField...)sectdict.setdefault('main','hidden')sectdict.setdefault('muledit','hidden')sectdict.setdefault('inlined','hidden')# ensure we have a tag for each form typeifnot'main'insectdict:ifnotrschema.finaland(sectdict.get('inlined')=='attributes'or'inlined_attributes'inself.init_get(sschema,rschema,oschema,neg_role(role))):sectdict['main']='hidden'elifsschema.is_metadata(rschema):sectdict['main']='metadata'else:card,composed=_card_and_comp(sschema,rschema,oschema,role)ifcardin'1+':sectdict['main']='attributes'ifnot'muledit'insectdict:sectdict['muledit']='attributes'elifrschema.final:sectdict['main']='attributes'else:sectdict['main']='relations'ifnot'muledit'insectdict:sectdict['muledit']='hidden'ifsectdict['main']=='attributes':card,composed=_card_and_comp(sschema,rschema,oschema,role)ifcardin'1+'andnotcomposed:sectdict['muledit']='attributes'ifnot'inlined'insectdict:sectdict['inlined']=sectdict['main']# recompute formsections and set it to avoid recomputingforformtype,sectioninsectdict.iteritems():formsections.add('%s_%s'%(formtype,section))deftag_relation(self,key,formtype,section):ifisinstance(formtype,tuple):forftypeinformtype:self.tag_relation(key,ftype,section)returnassertformtypeinself._allowed_form_types, \'formtype should be in (%s), not %s'%(','.join(self._allowed_form_types),formtype)assertsectioninself._allowed_values[formtype], \'section for %s should be in (%s), not %s'%(formtype,','.join(self._allowed_values[formtype]),section)rtags=self._tagdefs.setdefault(_ensure_str_key(key),self.tag_container_cls())# remove previous section for this form type if anyifrtags:fortaginrtags.copy():iftag.startswith(formtype):rtags.remove(tag)rtags.add('%s_%s'%(formtype,section))returnrtagsdefinit_get(self,stype,rtype,otype,tagged):key=(stype,rtype,otype,tagged)rtags={}forkeyinself._get_keys(stype,rtype,otype,tagged):tags=self._tagdefs.get(key,())fortagintags:assert'_'intag,(tag,tags)section,value=tag.split('_',1)rtags[section]=valuecls=self.tag_container_clsrtags=cls('_'.join([section,value])forsection,valueinrtags.iteritems())returnrtagsdefget(self,*key):# overriden to avoid recomputing done in parent classesreturnself._tagdefs.get(key,())defrelations_by_section(self,entity,formtype,section,permission,strict=False):"""return a list of (relation schema, target schemas, role) for the given entity matching categories and permission. `strict`: bool telling if having local role is enough (strict = False) or not """tag='%s_%s'%(formtype,section)eschema=entity.e_schemacw=entity._cwpermsoverrides=cw.vreg['uicfg'].select('autoform_permissions_overrides',cw,entity=entity)ifentity.has_eid():eid=entity.eidelse:eid=Nonestrict=Falseifpermission=='update':assertsectionin('attributes','metadata','hidden')relpermission='add'else:assertsectionnotin('attributes','metadata','hidden')relpermission=permissionforrschema,targetschemas,roleineschema.relation_definitions(True):_targetschemas=[]fortschemaintargetschemas:# check section's tag first, potentially lower cost than# checking permission which may imply rql queriesifnottaginself.etype_get(eschema,rschema,role,tschema):continuerdef=rschema.role_rdef(eschema,tschema,role)ifrschema.final:ifnotrdef.has_perm(cw,permission,eid=eid,creating=eidisNone):continueelifstrictornotrdef.has_local_role(relpermission):ifrole=='subject':ifnotrdef.has_perm(cw,relpermission,fromeid=eid):continueelifrole=='object':ifnotrdef.has_perm(cw,relpermission,toeid=eid):continue_targetschemas.append(tschema)ifnot_targetschemas:continuetargetschemas=_targetschemasrdef=eschema.rdef(rschema,role=role,targettype=targetschemas[0])# XXX tag allowing to hijack the permission machinery when# permission is not verifiable until the entity is actually# created...ifeidisNoneand'%s_on_new'%permissioninpermsoverrides.etype_get(eschema,rschema,role):yield(rschema,targetschemas,role)continueifnotrschema.finalandrole=='subject':# on relation with cardinality 1 or ?, we need delete perm as well# if the relation is already setif(relpermission=='add'andrdef.role_cardinality(role)in'1?'andeidandentity.related(rschema.type,role)andnotrdef.has_perm(cw,'delete',fromeid=eid,toeid=entity.related(rschema.type,role)[0][0])):continueelifrole=='object':# on relation with cardinality 1 or ?, we need delete perm as well# if the relation is already setif(relpermission=='add'andrdef.role_cardinality(role)in'1?'andeidandentity.related(rschema.type,role)andnotrdef.has_perm(cw,'delete',toeid=eid,fromeid=entity.related(rschema.type,role)[0][0])):continueyield(rschema,targetschemas,role)defhide_field(self,etype,attr,desttype='*',formtype='main'):"""hide `attr` in `etype` forms. :param etype: the entity type as a string :param attr: the name of the attribute or relation to hide :param formtype: which form will be affected ('main', 'inlined', etc.), *main* by default. `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_rel) Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_section as afs afs.hide_field('CWUser', 'login') afs.hide_field('*', 'name') afs.hide_field('CWUser', 'use_email', formtype='inlined') """self._tag_etype_attr(etype,attr,desttype,formtype=formtype,section='hidden')defhide_fields(self,etype,attrs,formtype='main'):"""simple for-loop wrapper around :func:`hide_field`. :param etype: the entity type as a string :param attrs: the ordered list of attribute names (or relations) :param formtype: which form will be affected ('main', 'inlined', etc.), *main* by default. `attrs` can be strings or 2-tuples (relname, role_of_etype_in_the_rel) Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_section as afs afs.hide_fields('CWUser', ('login', ('use_email', 'subject')), formtype='inlined') """forattrinattrs:self.hide_field(etype,attr,formtype=formtype)defedit_inline(self,etype,attr,desttype='*',formtype=('main','inlined')):"""edit `attr` with and inlined form. :param etype: the entity type as a string :param attr: the name of the attribute or relation :param desttype: the destination type(s) concerned, default is everything :param formtype: which form will be affected ('main', 'inlined', etc.), *main* and *inlined* by default. `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation) Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_section as afs afs.edit_inline('*', 'use_email') """self._tag_etype_attr(etype,attr,desttype,formtype=formtype,section='inlined')defedit_as_attr(self,etype,attr,desttype='*',formtype=('main','muledit')):"""make `attr` appear in the *attributes* section of `etype` form. :param etype: the entity type as a string :param attr: the name of the attribute or relation :param desttype: the destination type(s) concerned, default is everything :param formtype: which form will be affected ('main', 'inlined', etc.), *main* and *muledit* by default. `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation) Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_section as afs afs.edit_as_attr('CWUser', 'in_group') """self._tag_etype_attr(etype,attr,desttype,formtype=formtype,section='attributes')defset_muledit_editable(self,etype,attrs):"""make `attrs` appear in muledit form of `etype`. :param etype: the entity type as a string :param attrs: the ordered list of attribute names (or relations) `attrs` can be strings or 2-tuples (relname, role_of_etype_in_the_relation) Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_section as afs afs.set_muledit_editable('CWUser', ('firstname', 'surname', 'in_group')) """forattrinattrs:self.edit_as_attr(self,etype,attr,formtype='muledit')autoform_section=AutoformSectionRelationTags()# relations'field classclassAutoformFieldTags(RelationTags):__regid__='autoform_field'defset_field(self,etype,attr,field):"""sets the `attr` field of `etype`. :param etype: the entity type as a string :param attr: the name of the attribute or relation `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation) """self._tag_etype_attr(etype,attr,'*',field)autoform_field=AutoformFieldTags()# relations'field explicit kwargs (given to field's __init__)classAutoformFieldKwargsTags(RelationTagsDict):__regid__='autoform_field_kwargs'defset_fields_order(self,etype,attrs):"""specify the field order in `etype` main edition form. :param etype: the entity type as a string :param attrs: the ordered list of attribute names (or relations) `attrs` can be strings or 2-tuples (relname, role_of_etype_in_the_rel) Unspecified fields will be displayed after specified ones, their order being consistent with the schema definition. Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_field_kwargs as affk affk.set_fields_order('CWUser', ('firstname', 'surname', 'login')) affk.set_fields_order('CWUser', ('firstname', ('in_group', 'subject'), 'surname', 'login')) """forindex,attrinenumerate(attrs):self._tag_etype_attr(etype,attr,'*',{'order':index})defset_field_kwargs(self,etype,attr,**kwargs):"""tag `attr` field of `etype` with additional named paremeters. :param etype: the entity type as a string :param attr: the name of the attribute or relation `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation) Examples: .. sourcecode:: python from cubicweb.web.views.uicfg import autoform_field_kwargs as affk affk.set_field_kwargs('Person', 'works_for', widget=fwdgs.AutoCompletionWidget()) affk.set_field_kwargs('CWUser', 'login', label=_('login or email address'), widget=fwdgs.TextInput(attrs={'size': 30})) """self._tag_etype_attr(etype,attr,'*',kwargs)autoform_field_kwargs=AutoformFieldKwargsTags()# set of tags of the form <action>_on_new on relations. <action> is a# schema action (add/update/delete/read), and when such a tag is found# permissions checking is by-passed and supposed to be okclassAutoFormPermissionsOverrides(RelationTagsSet):__regid__='autoform_permissions_overrides'autoform_permissions_overrides=AutoFormPermissionsOverrides()classReleditTags(NoTargetRelationTagsDict):"""Associate to relation a dictionary to control `reledit` (e.g. edition of attributes / relations from within views). Possible keys and associated values are: * `novalue_label`, alternative default value (shown when there is no value). * `novalue_include_rtype`, when `novalue_label` is not specified, this boolean flag control wether the generated default value should contains the relation label or not. Will be the opposite of the `showlabel` value found in the `primaryview_display_ctrl` rtag by default. * `reload`, boolean, eid (to reload to) or function taking subject and returning bool/eid. This is useful when editing a relation (or attribute) that impacts the url or another parts of the current displayed page. Defaults to False. * `rvid`, alternative view id (as str) for relation or composite edition. Default is 'autolimited'. * `edit_target`, may be either 'rtype' (to edit the relation) or 'related' (to edit the related entity). This controls whether to edit the relation or the target entity of the relation. Currently only one-to-one relations support target entity edition. By default, the 'related' option is taken whenever the relation is composite. """__regid__='reledit'_keys=frozenset('novalue_label novalue_include_rtype reload rvid edit_target'.split())deftag_relation(self,key,tag):fortagkeyintag:asserttagkeyinself._keys,'tag %r not in accepted tags: %r'%(tag,self._keys)returnsuper(ReleditTags,self).tag_relation(key,tag)def_init(self,sschema,rschema,oschema,role):values=self.get(sschema,rschema,oschema,role)ifnotrschema.final:composite=rschema.rdef(sschema,oschema).composite==roleifrole=='subject':oschema='*'else:sschema='*'edittarget=values.get('edit_target')ifedittargetnotin(None,'rtype','related'):self.warning('reledit: wrong value for edit_target on relation %s: %s',rschema,edittarget)edittarget=Noneifnotedittarget:edittarget='related'ifcompositeelse'rtype'self.tag_relation((sschema,rschema,oschema,role),{'edit_target':edittarget})ifnot'novalue_include_rtype'invalues:showlabel=primaryview_display_ctrl.get(sschema,rschema,oschema,role).get('showlabel',True)self.tag_relation((sschema,rschema,oschema,role),{'novalue_include_rtype':notshowlabel})reledit_ctrl=ReleditTags()# boxes.EditBox configuration ################################################## 'link' / 'create' relation tags, used to control the "add entity" submenuclassActionBoxUicfg(RelationTagsBool):__regid__='actionbox_appearsin_addmenu'def_init(self,sschema,rschema,oschema,role):ifself.get(sschema,rschema,oschema,role)isNone:ifrschemainMETA_RTYPES:self.tag_relation((sschema,rschema,oschema,role),False)returnrdef=rschema.rdef(sschema,oschema)ifnotrdef.role_cardinality(role)in'?1'andrdef.composite==role:self.tag_relation((sschema,rschema,oschema,role),True)def_tag_etype_attr(self,etype,attr,desttype='*',*args,**kwargs):ifisinstance(attr,basestring):attr,role=attr,'subject'else:attr,role=attrifrole=='subject':self.tag_subject_of((etype,attr,desttype),*args,**kwargs)else:self.tag_object_of((desttype,attr,etype),*args,**kwargs)defappend_to_addmenu(self,etype,attr,createdtype='*'):"""adds `attr` in the actions box *addrelated* submenu of `etype`. :param etype: the entity type as a string :param attr: the name of the attribute or relation to hide :param createdtype: the target type of the relation (optional, defaults to '*' (all possible types)) `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation) """self._tag_etype_attr(etype,attr,createdtype,True)defremove_from_addmenu(self,etype,attr,createdtype='*'):"""removes `attr` from the actions box *addrelated* submenu of `etype`. :param etype: the entity type as a string :param attr: the name of the attribute or relation to hide :param createdtype: the target type of the relation (optional, defaults to '*' (all possible types)) `attr` can be a string or 2-tuple (relname, role_of_etype_in_the_relation) """self._tag_etype_attr(etype,attr,createdtype,False)actionbox_appearsin_addmenu=ActionBoxUicfg()defregistration_callback(vreg):vreg.register_all(globals().itervalues(),__name__)indexview_etype_section.init(vreg.schema)