Show
Ignore:
Timestamp:
08/08/08 16:05:30 (5 years ago)
Author:
Nicolas ?vrard <nicoe@…>
Children:
47:2cd126dda783, 51:3f7a7a668995
Branch:
default
Message:

Support for both text:a and text:placeholder tags in the opendocument plugin

Fixed tests that relied on the order of the PI in test_odt

Raise an error when the expression to evaluate is empty

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • relatorio/templates/opendocument.py

    r44 r46  
    3636from genshi.template import MarkupTemplate 
    3737 
    38 GENSHI_TAGS = re.compile(r'''relatorio://((/)?(for|choose|otherwise|when|if|with)( (\w+)=["'](.*)["']|)|.*)''') 
     38GENSHI_EXPR = re.compile(r'''((/)?(for|choose|otherwise|when|if|with)( (\w+)=["'](.*)["']|)|.*)''') 
    3939EXTENSIONS = {'image/png': 'png', 
    4040              'image/jpeg': 'jpg', 
     
    4747_encode = genshi.output.encode 
    4848ETElement = lxml.etree.Element 
     49 
     50 
     51class OOTemplateError(genshi.template.base.TemplateSyntaxError): 
     52    pass 
    4953 
    5054 
     
    112116 
    113117        self._invert_style(tree) 
    114         self._handle_text_a(tree) 
     118        self._handle_relatorio_tags(tree) 
    115119        self._handle_images(tree) 
    116120        self._handle_innerdocs(tree) 
     
    129133            span.append(text_a) 
    130134 
    131     def _handle_text_a(self, tree): 
     135    def _relatorio_statements(self, tree): 
     136        # If this node href matches the relatorio URL it is kept. 
     137        # If this node href matches a genshi directive it is kept for further 
     138        # processing. 
     139        r_statements, genshi_dir = [], [] 
     140        xlink_href_attrib = '{%s}href' % self.namespaces['xlink'] 
     141        text_a = '{%s}a' % self.namespaces['text'] 
     142        placeholder = '{%s}placeholder' % self.namespaces['text'] 
     143 
     144        s_xpath = "//text:a[starts-with(@xlink:href, 'relatorio://')]" \ 
     145                  "| //text:placeholder" 
     146        for statement in tree.xpath(s_xpath, namespaces=self.namespaces): 
     147            if statement.tag == placeholder: 
     148                expr = statement.text[1:-1] 
     149            elif statement.tag == text_a: 
     150                expr = urllib.unquote(statement.attrib[xlink_href_attrib][12:]) 
     151 
     152            if not expr: 
     153                raise OOTemplateError("No expression in the tag", 
     154                                      self.filepath) 
     155            elif not statement.text: 
     156                warnings.warn('No statement text in %s' % self.filepath) 
     157            elif expr != statement.text and statement.tag == text_a: 
     158                warnings.warn('url and text do not match in %s: %s != %s'  
     159                              % (self.filepath, expr, 
     160                                 statement.text.encode('utf-8'))) 
     161 
     162            match_obj = GENSHI_EXPR.match(expr) 
     163 
     164            expr, closing, directive, _, attr, attr_val = match_obj.groups() 
     165            if directive is not None: 
     166                genshi_dir.append((statement, closing)) 
     167            r_statements.append((statement,  
     168                                 (expr, closing, directive, attr, attr_val))) 
     169 
     170        return r_statements, genshi_dir 
     171 
     172    def _handle_relatorio_tags(self, tree): 
    132173        """ 
    133         Will treat all text:a tag (py:if/for/choose/when/otherwise) 
     174        Will treat all relatorio tag (py:if/for/choose/when/otherwise) 
    134175        tags 
    135176        """ 
     
    139180        office_name = '{%s}value' % self.namespaces['office'] 
    140181        office_valuetype = '{%s}value-type' % self.namespaces['office'] 
    141         genshi_name = '{%s}replace' % self.namespaces['py'] 
    142         xlink_href_attrib = '{%s}href' % self.namespaces['xlink'] 
    143  
    144         # First we create the list of all the text:a nodes. 
    145         # If this node href matches the relatorio URL it is kept. 
    146         # If this node href matches a genshi directive it is kept for further 
    147         # processing. 
    148         genshi_directives, text_a = [], [] 
    149         xpath_expr = "//text:a[starts-with(@xlink:href, 'relatorio://')]" 
    150         for statement in tree.xpath(xpath_expr, namespaces=self.namespaces): 
    151             href = urllib.unquote(statement.attrib[xlink_href_attrib]) 
    152             match_obj = GENSHI_TAGS.match(href) 
    153             expr, closing, directive, _, attr, attr_val = match_obj.groups() 
    154             if expr != statement.text: 
    155                 txt = statement.text or '' 
    156                 warnings.warn('url and text do not match in %s: %s != %s'  
    157                               % (self.filepath, expr, txt.encode('utf-8'))) 
    158             if directive is not None: 
    159                 genshi_directives.append((statement, href)) 
    160             text_a.append((statement,  
    161                            (expr, closing, directive, attr, attr_val))) 
    162  
    163         # Then we match the opening and closing directives together 
     182        genshi_replace = '{%s}replace' % self.namespaces['py'] 
     183 
     184        r_statements, genshi_directives = self._relatorio_statements(tree) 
     185        # We match the opening and closing directives together 
    164186        idx = 0 
    165187        genshi_pairs, inserted = [], [] 
    166         for statement, href in genshi_directives: 
    167             if not href.startswith('relatorio:///'): 
     188        for statement, closing in genshi_directives: 
     189            if closing is None: 
    168190                genshi_pairs.append([statement, None]) 
    169191                inserted.append(idx) 
     
    172194                genshi_pairs[inserted.pop()][1] = statement 
    173195 
    174         for a_node, parsed in text_a: 
     196        for r_node, parsed in r_statements: 
    175197            expr, c_dir, directive, attr, a_val = parsed 
    176198 
    177199            if directive is not None: 
    178                 # If the text:a is a genshi directive statement: 
     200                # If the node is a genshi directive statement: 
    179201                #    - we operate only on opening statement 
    180202                #    - we find the nearest ancestor of the closing and opening 
     
    190212                    continue 
    191213                for pair in genshi_pairs: 
    192                     if pair[0] == a_node: 
     214                    if pair[0] == r_node: 
    193215                        break 
    194216                opening, closing = pair 
     
    220242            else: 
    221243                # It's not a genshi statement it's a python expression 
    222                 a_node.attrib['{%s}replace' % self.namespaces['py']] = expr 
    223                 parent = a_node.getparent().getparent() 
     244                r_node.attrib[genshi_replace] = expr 
     245                parent = r_node.getparent().getparent() 
    224246                if parent is None or parent.tag != table_cell_tag: 
    225247                    continue