Package logilab-common-0 :: Package 39 :: Package 0 :: Package ureports
[frames] | no frames]

Source Code for Package logilab-common-0.39.0.ureports

  1  """Universal report objects and some formatting drivers. 
  2   
  3  A way to create simple reports using python objects, primarly designed to be 
  4  formatted as text and html. 
  5   
  6  :copyright: 
  7    2004-2008 `LOGILAB S.A. <http://www.logilab.fr>`_ (Paris, FRANCE), 
  8    all rights reserved. 
  9   
 10  :contact: 
 11    http://www.logilab.org/project/logilab-common -- 
 12    mailto:python-projects@logilab.org 
 13   
 14  :license: 
 15    `General Public License version 2 
 16    <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>`_ 
 17  """ 
 18  from __future__ import generators 
 19  __docformat__ = "restructuredtext en" 
 20   
 21  import sys 
 22  from cStringIO import StringIO 
 23  from StringIO import StringIO as UStringIO 
 24   
 25  from logilab.common.textutils import linesep 
 26   
 27   
28 -def get_nodes(node, klass):
29 """return an iterator on all children node of the given klass""" 30 for child in node.children: 31 if isinstance(child, klass): 32 yield child 33 # recurse (FIXME: recursion controled by an option) 34 for grandchild in get_nodes(child, klass): 35 yield grandchild
36
37 -def layout_title(layout):
38 """try to return the layout's title as string, return None if not found 39 """ 40 for child in layout.children: 41 if isinstance(child, Title): 42 return ' '.join([node.data for node in get_nodes(child, Text)])
43
44 -def build_summary(layout, level=1):
45 """make a summary for the report, including X level""" 46 assert level > 0 47 level -= 1 48 summary = List(klass='summary') 49 for child in layout.children: 50 if not isinstance(child, Section): 51 continue 52 label = layout_title(child) 53 if not label and not child.id: 54 continue 55 if not child.id: 56 child.id = label.replace(' ', '-') 57 node = Link('#'+child.id, label=label or child.id) 58 # FIXME: Three following lines produce not very compliant 59 # docbook: there are some useless <para><para>. They might be 60 # replaced by the three commented lines but this then produces 61 # a bug in html display... 62 if level and [n for n in child.children if isinstance(n, Section)]: 63 node = Paragraph([node, build_summary(child, level)]) 64 summary.append(node) 65 # summary.append(node) 66 # if level and [n for n in child.children if isinstance(n, Section)]: 67 # summary.append(build_summary(child, level)) 68 return summary
69 70
71 -class BaseWriter(object):
72 """base class for ureport writers""" 73
74 - def format(self, layout, stream=None, encoding=None):
75 """format and write the given layout into the stream object 76 77 unicode policy: unicode strings may be found in the layout; 78 try to call stream.write with it, but give it back encoded using 79 the given encoding if it fails 80 """ 81 if stream is None: 82 stream = sys.stdout 83 if not encoding: 84 encoding = getattr(stream, 'encoding', 'UTF-8') 85 self.encoding = encoding or 'UTF-8' 86 self.__compute_funcs = [] 87 self.out = stream 88 self.begin_format(layout) 89 layout.accept(self) 90 self.end_format(layout)
91
92 - def format_children(self, layout):
93 """recurse on the layout children and call their accept method 94 (see the Visitor pattern) 95 """ 96 for child in getattr(layout, 'children', ()): 97 child.accept(self)
98
99 - def writeln(self, string=''):
100 """write a line in the output buffer""" 101 self.write(string + linesep)
102
103 - def write(self, string):
104 """write a string in the output buffer""" 105 try: 106 self.out.write(string) 107 except UnicodeEncodeError: 108 self.out.write(string.encode(self.encoding))
109
110 - def begin_format(self, layout):
111 """begin to format a layout""" 112 self.section = 0
113
114 - def end_format(self, layout):
115 """finished to format a layout"""
116
117 - def get_table_content(self, table):
118 """trick to get table content without actually writing it 119 120 return an aligned list of lists containing table cells values as string 121 """ 122 result = [[]] 123 cols = table.cols 124 for cell in self.compute_content(table): 125 if cols == 0: 126 result.append([]) 127 cols = table.cols 128 cols -= 1 129 result[-1].append(cell) 130 # fill missing cells 131 while len(result[-1]) < cols: 132 result[-1].append('') 133 return result
134
135 - def compute_content(self, layout):
136 """trick to compute the formatting of children layout before actually 137 writing it 138 139 return an iterator on strings (one for each child element) 140 """ 141 # use cells ! 142 def write(data): 143 try: 144 stream.write(data) 145 except UnicodeEncodeError: 146 stream.write(data.encode(self.encoding))
147 def writeln(data=''): 148 try: 149 stream.write(data+linesep) 150 except UnicodeEncodeError: 151 stream.write(data.encode(self.encoding)+linesep)
152 self.write = write 153 self.writeln = writeln 154 self.__compute_funcs.append((write, writeln)) 155 for child in layout.children: 156 stream = UStringIO() 157 child.accept(self) 158 yield stream.getvalue() 159 self.__compute_funcs.pop() 160 try: 161 self.write, self.writeln = self.__compute_funcs[-1] 162 except IndexError: 163 del self.write 164 del self.writeln 165 166 167 from logilab.common.ureports.nodes import * 168 from logilab.common.ureports.text_writer import TextWriter 169 from logilab.common.ureports.html_writer import HTMLWriter 170