add a new method iter_process_result which does the same as proces_result but is a generator (closes #1625374)
process_result is reimplemented using the new method, and the two helper
methods are turned into generators.
These generators use cursor.fetchmany instead of cursor.fetchall after setting
cursor.arraysize to 100. This means that the whole result set should never
loaded in memory when using the iter_process_result method. This is used in the
"portable" database dump implementation when we typically to 'SELECT * FROM
table', but could probably be used too in other parts of cubicweb.
# copyright 2003-2010 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/>."""workflow related schemas"""__docformat__="restructuredtext en"_=unicodefromyams.buildobjsimport(EntityType,RelationType,SubjectRelation,RichString,String,Int)fromcubicweb.schemaimportRQLConstraint,RQLUniqueConstraintfromcubicweb.schemasimport(META_ETYPE_PERMS,META_RTYPE_PERMS,HOOKS_RTYPE_PERMS)classWorkflow(EntityType):__permissions__=META_ETYPE_PERMSname=String(required=True,indexed=True,internationalizable=True,maxsize=256)description=RichString(default_format='text/rest',description=_('semantic description of this workflow'))workflow_of=SubjectRelation('CWEType',cardinality='+*',description=_('entity types which may use this workflow'),constraints=[RQLConstraint('O final FALSE')])initial_state=SubjectRelation('State',cardinality='?*',constraints=[RQLConstraint('O state_of S',msg=_('state doesn\'t belong to this workflow'))],description=_('initial state for this workflow'))classdefault_workflow(RelationType):"""default workflow for an entity type"""__permissions__=META_RTYPE_PERMSsubject='CWEType'object='Workflow'cardinality='?*'constraints=[RQLConstraint('S final FALSE, O workflow_of S',msg=_('workflow isn\'t a workflow for this type'))]classState(EntityType):"""used to associate simple states to an entity type and/or to define workflows """__permissions__=META_ETYPE_PERMSname=String(required=True,indexed=True,internationalizable=True,maxsize=256,constraints=[RQLUniqueConstraint('S name N, S state_of WF, Y state_of WF, Y name N','Y',_('workflow already have a state of that name'))])description=RichString(default_format='text/rest',description=_('semantic description of this state'))# XXX should be on BaseTransition w/ AND/OR selectors when we will# implements #345274allowed_transition=SubjectRelation('BaseTransition',cardinality='**',constraints=[RQLConstraint('S state_of WF, O transition_of WF',msg=_('state and transition don\'t belong the the same workflow'))],description=_('allowed transitions from this state'))state_of=SubjectRelation('Workflow',cardinality='1*',composite='object',description=_('workflow to which this state belongs'),constraints=[RQLUniqueConstraint('S name N, Y state_of O, Y name N','Y',_('workflow already have a state of that name'))])classBaseTransition(EntityType):"""abstract base class for transitions"""__permissions__=META_ETYPE_PERMSname=String(required=True,indexed=True,internationalizable=True,maxsize=256,constraints=[RQLUniqueConstraint('S name N, S transition_of WF, Y transition_of WF, Y name N','Y',_('workflow already have a transition of that name'))])type=String(vocabulary=(_('normal'),_('auto')),default='normal')description=RichString(description=_('semantic description of this transition'))condition=SubjectRelation('RQLExpression',cardinality='*?',composite='subject',description=_('a RQL expression which should return some results, ''else the transition won\'t be available. ''This query may use X and U variables ''that will respectivly represents ''the current entity and the current user'))require_group=SubjectRelation('CWGroup',cardinality='**',description=_('group in which a user should be to be ''allowed to pass this transition'))transition_of=SubjectRelation('Workflow',cardinality='1*',composite='object',description=_('workflow to which this transition belongs'),constraints=[RQLUniqueConstraint('S name N, Y transition_of O, Y name N','Y',_('workflow already have a transition of that name'))])classTransition(BaseTransition):"""use to define a transition from one or multiple states to a destination states in workflow's definitions. Transition without destination state will go back to the state from which we arrived to the current state. """__specializes_schema__=Truedestination_state=SubjectRelation('State',cardinality='?*',constraints=[RQLConstraint('S transition_of WF, O state_of WF',msg=_('state and transition don\'t belong the the same workflow'))],description=_('destination state for this transition'))classWorkflowTransition(BaseTransition):"""special transition allowing to go through a sub-workflow"""__specializes_schema__=Truesubworkflow=SubjectRelation('Workflow',cardinality='1*',constraints=[RQLConstraint('S transition_of WF, WF workflow_of ET, O workflow_of ET',msg=_('subworkflow isn\'t a workflow for the same types as the transition\'s workflow'))])# XXX use exit_of and inline itsubworkflow_exit=SubjectRelation('SubWorkflowExitPoint',cardinality='*1',composite='subject')classSubWorkflowExitPoint(EntityType):"""define how we get out from a sub-workflow"""subworkflow_state=SubjectRelation('State',cardinality='1*',constraints=[RQLConstraint('T subworkflow_exit S, T subworkflow WF, O state_of WF',msg=_('exit state must be a subworkflow state'))],description=_('subworkflow state'))destination_state=SubjectRelation('State',cardinality='?*',constraints=[RQLConstraint('T subworkflow_exit S, T transition_of WF, O state_of WF',msg=_('destination state must be in the same workflow as our parent transition'))],description=_('destination state. No destination state means that transition ''should go back to the state from which we\'ve entered the ''subworkflow.'))classTrInfo(EntityType):"""workflow history item"""# 'add' security actually done by hooks__permissions__={'read':('managers','users','guests',),# XXX U has_read_permission O ?'add':('managers','users','guests',),'delete':(),# XXX should we allow managers to delete TrInfo?'update':('managers','owners',),}# The unique_together constraint ensures that 2 repositories# sharing the db won't be able to fire a transition simultaneously# on the same entity tr_count is filled in the FireTransitionHook# to the number of TrInfo attached to the entity on which we# attempt to fire a transition. In other word, it contains the# rank of the TrInfo for that entity, and the constraint says we# cannot have 2 TrInfo with the same rank.__unique_together__=[('tr_count','wf_info_for')]from_state=SubjectRelation('State',cardinality='1*',inlined=True)to_state=SubjectRelation('State',cardinality='1*',inlined=True)# make by_transition optional because we want to allow managers to set# entity into an arbitrary state without having to respect wf transitionby_transition=SubjectRelation('BaseTransition',cardinality='?*')comment=RichString(fulltextindexed=True)tr_count=Int(description='autocomputed attribute used to ensure transition coherency')# get actor and date time using owned_by and creation_dateclassfrom_state(RelationType):__permissions__=HOOKS_RTYPE_PERMS.copy()inlined=Trueclassto_state(RelationType):__permissions__=HOOKS_RTYPE_PERMS.copy()inlined=Trueclassby_transition(RelationType):# 'add' security actually done by hooks__permissions__={'read':('managers','users','guests',),'add':('managers','users','guests',),'delete':(),}inlined=Trueclassworkflow_of(RelationType):"""link a workflow to one or more entity type"""__permissions__=META_RTYPE_PERMSclassstate_of(RelationType):"""link a state to one or more workflow"""__permissions__=META_RTYPE_PERMSinlined=Trueclasstransition_of(RelationType):"""link a transition to one or more workflow"""__permissions__=META_RTYPE_PERMSinlined=Trueclassdestination_state(RelationType):"""destination state of a transition"""__permissions__=META_RTYPE_PERMSinlined=Trueclassallowed_transition(RelationType):"""allowed transitions from this state"""__permissions__=META_RTYPE_PERMSclassinitial_state(RelationType):"""indicate which state should be used by default when an entity using states is created """__permissions__=META_RTYPE_PERMSinlined=Trueclasssubworkflow(RelationType):__permissions__=META_RTYPE_PERMSinlined=Trueclassexit_point(RelationType):__permissions__=META_RTYPE_PERMSclasssubworkflow_state(RelationType):__permissions__=META_RTYPE_PERMSinlined=Trueclasscondition(RelationType):__permissions__=META_RTYPE_PERMS# already defined in base.py# class require_group(RelationType):# __permissions__ = META_RTYPE_PERMS# "abstract" relations, set by WorkflowableEntityType ##########################classcustom_workflow(RelationType):"""allow to set a specific workflow for an entity"""__permissions__=META_RTYPE_PERMScardinality='?*'constraints=[RQLConstraint('S is ET, O workflow_of ET',msg=_('workflow isn\'t a workflow for this type'))]object='Workflow'classwf_info_for(RelationType):"""link a transition information to its object"""# 'add' security actually done by hooks__permissions__={'read':('managers','users','guests',),'add':('managers','users','guests',),'delete':(),}inlined=Truecardinality='1*'composite='object'fulltext_container=compositesubject='TrInfo'classin_state(RelationType):"""indicate the current state of an entity"""__permissions__=HOOKS_RTYPE_PERMS# not inlined intentionnaly since when using ldap sources, user'state# has to be stored outside the CWUser tableinlined=Falsecardinality='1*'constraints=[RQLConstraint('S is ET, O state_of WF, WF workflow_of ET',msg=_('state doesn\'t apply to this entity\'s type'))]object='State'