sobjects/textparsers.py
changeset 11057 0b59724cb3f2
parent 11052 058bb3dc685f
child 11058 23eb30449fe5
equal deleted inserted replaced
11052:058bb3dc685f 11057:0b59724cb3f2
     1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     3 #
       
     4 # This file is part of CubicWeb.
       
     5 #
       
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
       
     7 # terms of the GNU Lesser General Public License as published by the Free
       
     8 # Software Foundation, either version 2.1 of the License, or (at your option)
       
     9 # any later version.
       
    10 #
       
    11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT
       
    12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
       
    14 # details.
       
    15 #
       
    16 # You should have received a copy of the GNU Lesser General Public License along
       
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
       
    18 """Some parsers to detect action to do from text
       
    19 
       
    20 Currently only a parser to look for state change instruction is provided.
       
    21 Take care to security when you're using it, think about the user that
       
    22 will provide the text to analyze...
       
    23 """
       
    24 
       
    25 __docformat__ = "restructuredtext en"
       
    26 
       
    27 import re
       
    28 
       
    29 from cubicweb import UnknownEid
       
    30 from cubicweb.view import Component
       
    31 
       
    32 
       
    33 class TextAnalyzer(Component):
       
    34     """analyze and extract information from plain text by calling registered
       
    35     text parsers
       
    36     """
       
    37     __regid__ = 'textanalyzer'
       
    38 
       
    39     def parse(self, caller, text):
       
    40         for parsercls in self._cw.vreg['components'].get('textparser', ()):
       
    41             parsercls(self._cw).parse(caller, text)
       
    42 
       
    43 
       
    44 class TextParser(Component):
       
    45     """base class for text parser, responsible to extract some information
       
    46     from plain text. When something is done, it usually call the
       
    47 
       
    48       .fire_event(something, {event args})
       
    49 
       
    50     method on the caller.
       
    51     """
       
    52     __regid__ = 'textparser'
       
    53     __abstract__ = True
       
    54 
       
    55     def parse(self, caller, text):
       
    56         raise NotImplementedError
       
    57 
       
    58 
       
    59 class ChangeStateTextParser(TextParser):
       
    60     """search some text for change state instruction in the form
       
    61 
       
    62          :<transition name>: #?<eid>
       
    63     """
       
    64     instr_rgx = re.compile(':(\w+):\s*#?(\d+)', re.U)
       
    65 
       
    66     def parse(self, caller, text):
       
    67         for trname, eid in self.instr_rgx.findall(text):
       
    68             try:
       
    69                 entity = self._cw.entity_from_eid(int(eid))
       
    70             except UnknownEid:
       
    71                 self.error("can't get entity with eid %s", eid)
       
    72                 continue
       
    73             if not hasattr(entity, 'in_state'):
       
    74                 self.error('bad change state instruction for eid %s', eid)
       
    75                 continue
       
    76             iworkflowable = entity.cw_adapt_to('IWorkflowable')
       
    77             if iworkflowable.current_workflow:
       
    78                 tr = iworkflowable.current_workflow.transition_by_name(trname)
       
    79             else:
       
    80                 tr = None
       
    81             if tr and tr.may_be_fired(entity.eid):
       
    82                 try:
       
    83                     trinfo = iworkflowable.fire_transition(tr)
       
    84                     caller.fire_event('state-changed', {'trinfo': trinfo,
       
    85                                                         'entity': entity})
       
    86                 except Exception:
       
    87                     self.exception('while changing state of %s', entity)
       
    88             else:
       
    89                 self.error("can't pass transition %s on entity %s",
       
    90                            trname, entity)