def getMoverTableRows(self,tablerow=None,movercode=None,**kwargs): pkeys = tablerow['pkeys'].keys() table = tablerow['table'] objtype = tablerow['objtype'] tblobj = self.db.table(table) columns,mask = tblobj.rowcaptionDecode(tblobj.rowcaption) if columns: columns = ','.join(columns) f = tblobj.query(where='$pkey IN :pkeys',pkeys=tablerow['pkeys'].keys(),columns=columns).fetch() result = Bag() for r in f: result.setItem(r['pkey'],None,_pkey=r['pkey'],db_caption=tblobj.recordCaption(record=r),_customClasses='mover_db') indexpath = self.page.site.getStaticPath('user:temp','mover','index.xml') if os.path.isfile(indexpath): indexbag = Bag(indexpath) moverrows = indexbag.getItem('records.%s' %movercode) if not moverrows: return result for pkey in pkeys: rownode = moverrows.getNode(pkey) if rownode: xml_caption=rownode.attr['caption'] if not pkey in result: result.setItem(pkey,None,_pkey=pkey,xml_caption=xml_caption,_customClasses='mover_xml',objtype=objtype,table=tablerow['reftable']) else: result.getNode(pkey).attr.update(xml_caption=xml_caption,_customClasses='mover_both',objtype=objtype,table=tablerow['reftable']) return result
def importMoverLines(self, table=None, objtype=None, pkeys=None): databag = Bag( self.page.site.getStaticPath("user:temp", "mover", "data", "%s_%s.xml" % (table.replace(".", "_"), objtype)) ) tblobj = self.db.table(table) if objtype == "record" else self.db.table("adm.userobject") for pkey in pkeys.keys(): tblobj.insertOrUpdate(databag.getItem(pkey)) self.db.commit()
def importMoverLines(self, table=None, objtype=None, pkeys=None): databag = Bag( self.page.site.getStaticPath( 'user:temp', 'mover', 'data', '%s_%s.xml' % (table.replace('.', '_'), objtype))) tblobj = self.db.table( table) if objtype == 'record' else self.db.table('adm.userobject') for pkey in pkeys.keys(): tblobj.insertOrUpdate(databag.getItem(pkey)) self.db.commit()
def getMoverTableRows(self, tablerow=None, movercode=None, **kwargs): pkeys = tablerow['pkeys'].keys() table = tablerow['table'] objtype = tablerow['objtype'] tblobj = self.db.table(table) columns, mask = tblobj.rowcaptionDecode(tblobj.rowcaption) if columns: columns = ','.join(columns) f = tblobj.query(where='$pkey IN :pkeys', pkeys=tablerow['pkeys'].keys(), columns=columns).fetch() result = Bag() for r in f: result.setItem(r['pkey'], None, _pkey=r['pkey'], db_caption=tblobj.recordCaption(record=r), _customClasses='mover_db') indexpath = self.page.site.getStaticPath('user:temp', 'mover', 'index.xml') if os.path.isfile(indexpath): indexbag = Bag(indexpath) moverrows = indexbag.getItem('records.%s' % movercode) if not moverrows: return result for pkey in pkeys: rownode = moverrows.getNode(pkey) if rownode: xml_caption = rownode.attr['caption'] if not pkey in result: result.setItem(pkey, None, _pkey=pkey, xml_caption=xml_caption, _customClasses='mover_xml', objtype=objtype, table=tablerow['reftable']) else: result.getNode(pkey).attr.update( xml_caption=xml_caption, _customClasses='mover_both', objtype=objtype, table=tablerow['reftable']) return result
def getMoverTableRows(self, tablerow=None, movercode=None, **kwargs): pkeys = tablerow["pkeys"].keys() table = tablerow["table"] objtype = tablerow["objtype"] tblobj = self.db.table(table) columns, mask = tblobj.rowcaptionDecode(tblobj.rowcaption) if columns: columns = ",".join(columns) f = tblobj.query(where="$pkey IN :pkeys", pkeys=tablerow["pkeys"].keys(), columns=columns).fetch() result = Bag() for r in f: result.setItem( r["pkey"], None, _pkey=r["pkey"], db_caption=tblobj.recordCaption(record=r), _customClasses="mover_db" ) indexpath = self.page.site.getStaticPath("user:temp", "mover", "index.xml") if os.path.isfile(indexpath): indexbag = Bag(indexpath) moverrows = indexbag.getItem("records.%s" % movercode) if not moverrows: return result for pkey in pkeys: rownode = moverrows.getNode(pkey) if rownode: xml_caption = rownode.attr["caption"] if not pkey in result: result.setItem( pkey, None, _pkey=pkey, xml_caption=xml_caption, _customClasses="mover_xml", objtype=objtype, table=tablerow["reftable"], ) else: result.getNode(pkey).attr.update( xml_caption=xml_caption, _customClasses="mover_both", objtype=objtype, table=tablerow["reftable"], ) return result
class BagToHtml(object): """A class that transforms a :ref:`bag` into HTML. It can be used to make a :ref:`print`""" css_requires = '' templates = '' letterhead_id = '' currencyFormat = u'#,###.00' encoding = 'utf-8' page_debug = False page_width = 200 page_height = 280 page_margin_top = 0 page_margin_left = 0 page_margin_right = 0 page_margin_bottom = 0 page_header_height = 0 page_footer_height = 0 page_leftbar_width = 0 page_rightbar_width = 0 print_button = None row_mode = 'value' rows_path = 'rows' doc_header_height = 0 # e.g. 10 doc_footer_height = 0 # e.g. 15 grid_header_height = 0 # e.g. 6.2 grid_footer_height = 0 grid_col_headers = None grid_col_widths = [0, 0, 0] grid_row_height = 5 copies_per_page = 1 copy_extra_height = 0 starting_page_number = 0 body_attributes = None def __init__(self, locale='en', encoding='utf-8', templates=None, templateLoader=None, **kwargs): self.locale = locale self.encoding = encoding self.thermo_kwargs = None self.thermo_wrapper = None if templates: self.templates = templates if templateLoader: self.templateLoader = templateLoader def init(self, *args, **kwargs): """A ``init`` hook method""" pass def outputDocName(self, ext=''): """Set the filename extension and return it :param ext: the filename extension""" return 'temp.%s' % ext def onRecordLoaded(self): """Hook method. Allow to define the query to be executed for the :ref:`print` Example:: def onRecordLoaded(self): where = '$date >= :begin_date AND $date <= :end_date AND doctor_id=:d_id' columns ='''$doctor,$date,$hour,$patient,$performance, @convention_id.code AS convention_code, $amount,$cost,@invoice_id.number AS invoice''' query = self.db.table(self.rows_table).query(columns=columns, where=where, begin_data = self.getData('period.from'), end_data = self.getData('period.to'), d_id=self.record['id']) selection = query.selection() if not selection: return False self.setData('rows',selection.output('grid'))""" pass def orientation(self): """Set the page orientation to 'Landscape' if the :ref:`bagtohtml_page_width` is greater than the :ref:`bagtohtml_page_height`, else set the orientation to 'Portrait'""" if self.page_width>self.page_height: return 'Landscape' else: return 'Portrait' def __call__(self, record=None, filepath=None, folder=None, filename=None, hideTemplate=False, rebuild=True, htmlContent=None,page_debug=None, is_draft=None, **kwargs): """Return the html corresponding to a given record. The html can be loaded from a cached document or created as new if still doesn't exist""" if record is None: record = Bag() self.htmlContent = htmlContent self._data = Bag() self.is_draft = is_draft self.record = record self.setData('record', record) #compatibility for k, v in kwargs.items(): self.setData(k, v) if not filepath: folder = folder or tempfile.mkdtemp() filepath = os.path.join(folder, filename or self.outputDocName(ext='html')) self.filepath = filepath if not rebuild: with open(self.filepath, 'r') as f: result = f.read() return result self.templates = kwargs.pop('templates', self.templates) self.letterhead_id = kwargs.pop('letterhead_id', self.letterhead_id) self.print_button = kwargs.pop('print_button', self.print_button) if self.onRecordLoaded() is False: return False self.showTemplate(hideTemplate is not True) self.htmlTemplate = None self.prepareTemplates() self.page_debug = page_debug or self.page_debug self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height, page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom, page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right, page_debug=self.page_debug, print_button=self.print_button, htmlTemplate=self.htmlTemplate, css_requires=self.get_css_requires(), showTemplateContent=self.showTemplateContent,parent=self) result = self.createHtml(filepath=self.filepath,body_attributes=self.body_attributes) return result def get_css_requires(self): """Get the :ref:`"css_requires" webpage variable <css_requires>` in its string format and return it as a list""" return self.css_requires.split(',') def prepareTemplates(self): """Set the correct value of every measure of the page: height, width, header, footer, margins""" top_layer = Bag() if not self.htmlTemplate: self.htmlTemplate = self.templateLoader(letterhead_id=self.letterhead_id,name=self.templates) if self.htmlTemplate: top_layer = self.htmlTemplate['#%i' %(len(self.htmlTemplate)-1)] d = self.__dict__ self.page_height = float(d.get('page_height') or top_layer['main.page.height'] or self.page_height) self.page_width = float(d.get('page_width') or top_layer['main.page.width'] or self.page_width) self.page_margin_top = float(d.get('page_margin_top') or top_layer['main.page.top'] or self.page_margin_top) self.page_margin_left = float(d.get('page_margin_left')or top_layer['main.page.left'] or self.page_margin_left) self.page_margin_right = float(d.get('page_margin_right')or top_layer['main.page.right'] or self.page_margin_right) self.page_margin_bottom = float(d.get('page_margin_bottom') or top_layer['main.page.bottom'] or self.page_margin_bottom) self.page_header_height = float(d.get('page_header_height') or top_layer['layout.top?height'] or self.page_header_height) self.page_footer_height = float(d.get('page_footer_height') or top_layer['layout.bottom?height'] or self.page_footer_height) self.page_leftbar_width = float(d.get('page_leftbar_width') or top_layer['layout.left?width'] or self.page_leftbar_width) self.page_rightbar_width = float(d.get('page_rightbar_width')or top_layer['layout.right?width'] or self.page_rightbar_width) def toText(self, obj, locale=None, format=None, mask=None, encoding=None, **kwargs): """TODO :param obj: TODO :param locale: the current locale (e.g: en, en_us, it) :param format: TODO :param mask: TODO :param encoding: the multibyte character encoding you choose""" locale = locale or self.locale encoding = locale or self.encoding return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding, **kwargs) def createHtml(self, filepath=None, body_attributes=None): """TODO :param filepath: the path where html will be saved""" #filepath = filepath or self.filepath self.initializeBuilder(body_attributes=body_attributes) self.main() self.builder.toHtml(filepath=filepath) return self.builder.html def showTemplate(self, value): """TODO :param value: TODO""" self.showTemplateContent = value def setTemplates(self, templates): """Set a template. :param templates: TODO""" self.templates = templates def getTemplates(self, templates): """TODO :param templates: TODO""" return self.templates def initializeBuilder(self, body_attributes=None): """TODO""" self.builder.initializeSrc(body_attributes=body_attributes) self.body = self.builder.body self.getNewPage = self.builder.newPage self.builder.styleForLayout() def getNewPage(self): pass def getData(self, path, default=None): """Make a :meth:`getItem() <gnr.core.gnrbag.Bag.getItem>` on data if ... TODO :param path: the path of data (e.g: ``'period.from'``) :param default: the default return value for a not found item""" wildchars = [] if path[0] in wildchars: value = 'not yet implemented' else: value = self._data.getItem(path, default) return value def setData(self, path, value, **kwargs): """Make a :meth:`setItem() <gnr.core.gnrbag.Bag.setItem>` on data :param path: the path of data (e.g: ``'period.from'``) :param default: the default return value for a not found item""" self._data.setItem(path, value, **kwargs) def onRecordExit(self, recordBag): """Hook method. :param recordBag: a :ref:`bag` that contains the result of the batch""" return def field(self, path, default=None, locale=None, format=None, mask=None, root=None, **kwargs): """TODO :param path: TODO :param default: TODO :param locale: the current locale (e.g: en, en_us, it) :param format: TODO :param mask: TODO :param root: the root of the page. For more information, check the :ref:`webpages_main` documentation section""" if root is None: root = self._data['record'] attr = {} if isinstance(root, Bag): datanode = root.getNode(path) if datanode: value = datanode.value attr = datanode.attr else: value = default else: value = root.get(path) format = format or attr.get('format') mask = mask or attr.get('mask') if value is None: value = default elif isinstance(value, Bag) and not format: return value return self.toText(value, locale, format, mask, self.encoding, **kwargs) def main(self): """It can be overridden""" if self.htmlContent: page = self.getNewPage() page.div("%s::HTML" % self.htmlContent) else: self.mainLoop() def onNewPage(self,page): if self.is_draft: page.div(style='position:absolute; top:0; left:0; right:0; bottom:0; z-index:10000',_class='document_draft') def pageCounter(self, mask=None): """Allow to automatically number the pages created in a :ref:`print`. You can choose the format output with the *mask* parameter :param mask: format output of the pageCounter method. By default is ``'%s/%s'`` **Example**: if you print three pages then they will be numbered as `1/3`, `2/3` and `3/3` **Syntax**: You can alternatively set it as ``'%s of %s'``, ``'%s - %s'`` and so on""" mask = mask or '%s/%s' def getPage(currPage=0): t = (currPage + 1 + self.starting_page_number, self.current_page_number + 1 + self.starting_page_number) if len(mask)-len(mask.replace(r'%s',''))>2: result = mask % t else: result = mask % t[0] return result return BagCbResolver(getPage, currPage=self.current_page_number) @property def current_page_number(self): return self.copies[self.copy]['currPage'] def copyHeight(self): """TODO""" return (self.page_height - self.page_margin_top - self.page_margin_bottom -\ self.page_header_height - self.page_footer_height -\ self.copy_extra_height * (self.copies_per_page - 1)) / self.copies_per_page def copyWidth(self): """TODO""" return (self.page_width - self.page_margin_left - self.page_margin_right -\ self.page_leftbar_width - self.page_rightbar_width) def mainLoop(self): """TODO""" self.copies = [] self.lastPage = False self.defineStandardStyles() self.defineCustomStyles() self.doc_height = self.copyHeight() #- self.page_header_height - self.page_footer_height self.grid_height = self.doc_height - self.calcDocHeaderHeight() - self.calcDocFooterHeight() self.grid_body_height = float(self.grid_height or 0) - float(self.grid_header_height or 0) - float(self.grid_footer_height or 0) for copy in range(self.copies_per_page): self.copies.append(dict(grid_body_used=self.grid_height, currPage=-1)) lines = self.getData(self.rows_path) if not lines and hasattr(self,'empty_row'): lines = Bag() lines.setItem('empty',Bag(self.empty_row),**self.empty_row) if lines: if isinstance(lines, Bag): nodes = lines.getNodes() elif hasattr(lines, 'next'): nodes = list(lines) else: nodes = lines lastNode = nodes[-1] if hasattr(self, 'thermo_wrapper') and self.thermo_kwargs: nodes = self.thermo_wrapper(nodes, **self.thermo_kwargs) for rowDataNode in nodes: self.isLastRow = rowDataNode is lastNode self.currRowDataNode = rowDataNode for copy in range(self.copies_per_page): self.onNewRow() self.copy = copy rowheight = self.calcRowHeight() availableSpace = self.grid_height - self.copyValue('grid_body_used') -\ self.calcGridHeaderHeight() - self.calcGridFooterHeight() if rowheight > availableSpace: self._newPage() if not self.rowData: continue row = self.copyValue('body_grid').row(height=rowheight) self.copies[self.copy]['grid_body_used'] = self.copyValue('grid_body_used') + rowheight self.currColumn = 0 self.currRow = row self.prepareRow(row) for copy in range(self.copies_per_page): self.copy = copy self._closePage(True) def onNewRow(self): pass def _newPage(self): if self.copyValue('currPage') >= 0: self._closePage() self.copies[self.copy]['currPage'] = self.copyValue('currPage') + 1 self.copies[self.copy]['grid_body_used'] = 0 self._createPage() self._openPage() def _get_rowData(self): if isinstance(self.currRowDataNode, dict) or isinstance(self.currRowDataNode,Bag): return self.currRowDataNode elif self.row_mode == 'attribute': return self.currRowDataNode.attr else: return self.currRowDataNode.value rowData = property(_get_rowData) def rowField(self, path=None, **kwargs): """TODO :param path: TODO""" #if self.row_mode=='attribute': # data = self.currRowDataNode.attr #else: # data = self.currRowDataNode.value return self.field(path, root=self.rowData, **kwargs) def rowCell(self, field=None, value=None, default=None, locale=None, format=None, mask=None, currency=None,white_space='nowrap', **kwargs): """Allow to get data from record. You can use it in the :meth:`prepareRow` method :param field: the name of the table :ref:`column` :param value: TODO :param default: TODO :param locale: the current locale (e.g: en, en_us, it) :param format: the format of the cell (e.g: use ``HH:mm``) :param mask: TODO :param currency: TODO""" if field: if callable(field): value = field() else: value = self.rowField(field, default=default, locale=locale, format=format, mask=mask, currency=currency) if value is not None: #if self.lastPage: # print 'last page' # print self.currColumn # print self.grid_col_widths[self.currColumn] value = self.toText(value, locale, format, mask, self.encoding) self.currRow.cell(value, width=self.grid_col_widths[self.currColumn], overflow='hidden', white_space=white_space, **kwargs) self.currColumn = self.currColumn + 1 return value def _createPage(self): curr_copy = self.copies[self.copy] if self.copy == 0: self.paperPage = self.getNewPage() #self.page_header_height = self.page_header_height or getattr(self.builder,'page_header_height') #self.page_footer_height = self.page_footer_height or getattr(self.builder,'page_footer_height') self.page_layout = self.mainLayout(self.paperPage) #if self.page_header_height: # curr_copy['page_header'] = self.page_layout.row(height=self.page_header_height,lbl_height=4,lbl_class='caption').cell() if self.calcDocHeaderHeight(): curr_copy['doc_header'] = self.page_layout.row(height=self.calcDocHeaderHeight(), lbl_height=4, lbl_class='caption').cell() curr_copy['doc_body'] = self.page_layout.row(height=0, lbl_height=4, lbl_class='caption').cell() if self.calcDocFooterHeight(): curr_copy['doc_footer'] = self.page_layout.row(height=self.doc_footer_height, lbl_height=4, lbl_class='caption').cell() #if self.page_footer_height: # curr_copy['page_footer'] = self.page_layout.row(height=self.page_footer_height,lbl_height=4,lbl_class='caption').cell() def mainLayout(self, page): """Hook method that must be overridden. It gives the :ref:`print_layout_page` object to which you have to append a :meth:`layout <gnr.core.gnrhtml.GnrHtmlSrc.layout>` :param page: the page object""" print 'mainLayout must be overridden' def _openPage(self): #if self.page_header_height: # self.pageHeader(self.copyValue('page_header')) #makeTop if self.doc_header_height: self.docHeader(self.copyValue('doc_header')) self._docBody(self.copyValue('doc_body')) def _closePage(self, lastPage=None): if lastPage: self.lastPage = True self.fillBodyGrid() footer_height = self.calcGridFooterHeight() if footer_height: row = self.copyValue('body_grid').row(height=footer_height) self.currColumn = 0 self.currRow = row self.gridFooter(row) if self.calcDocFooterHeight(): self.docFooter(self.copyValue('doc_footer'), lastPage=lastPage) #if self.page_footer_height: # self.pageFooter(self.copyValue('page_footer'),lastPage=lastPage) def _docBody(self, body): header_height = self.calcGridHeaderHeight() grid = self.gridLayout(body) if header_height: self.gridHeader(grid.row(height=header_height)) self.copies[self.copy]['body_grid'] = grid def gridLayout(self, grid): """Hook method. MANDATORY if you define a :ref:`print_layout_grid` in your :ref:`print`. Through this method you receive the center of the page and you can define the layout of the grid :param grid: the :ref:`print_layout_grid`""" print 'gridLayout must be overridden' def gridHeader(self, row): """It can be overridden :param row: the grid row""" lbl_height = 4 headers = self.grid_col_headers if ':' in headers: headers, lbl_height = headers.split(':') lbl_height = int(lbl_height) for k, lbl in enumerate(self.grid_col_headers.split(',')): style = None if lbl == '|': lbl = '' style = 'border-top:0mm;border-bottom:0mm;' row.cell(lbl=lbl, lbl_height=lbl_height, width=self.grid_col_widths[k], style=style) def gridFooter(self, row): """It can be overridden :param row: the grid row""" return def fillBodyGrid(self): """TODO""" row = self.copyValue('body_grid').row() for w in self.grid_col_widths: row.cell(width=w) def copyValue(self, valuename): """TODO :param valuename: the name of the value to copy""" return self.copies[self.copy][valuename] def calcRowHeight(self): """override for special needs""" return self.grid_row_height def calcGridHeaderHeight(self): """override for special needs""" return self.grid_header_height def calcGridFooterHeight(self): """override for special needs""" return self.grid_footer_height def calcDocHeaderHeight(self): """override for special needs""" return self.doc_header_height def calcDocFooterHeight(self): """override for special needs""" return self.doc_footer_height def defineCustomStyles(self): """override this for custom styles""" pass def docFooter(self, footer, lastPage=None): """Hook method. Define the footer of the :ref:`print_layout_doc` in the :ref:`print_layout` :param footer: the footer object :param lastPage: boolean. More information in the :ref:`lastpage` section .. note:: the method is called only if the :ref:`bagtohtml_doc_footer_height` has a value different from ``0``""" pass def pageFooter(self, footer, lastPage=None): """Hook method. Define the footer of the :ref:`print_layout_page` in the :ref:`print_layout` :param footer: the footer object :param lastPage: boolean. More information in the :ref:`lastpage` section .. note:: the method is called only if the :ref:`bagtohtml_page_footer_height` has a value different from ``0``""" pass def pageHeader(self, header): """Hook method. Define the header of the :ref:`print_layout_page` in the :ref:`print_layout` :param header: the header object .. note:: the method is called only if the :ref:`bagtohtml_page_header_height` has a value different from ``0``""" pass def docHeader(self, header): """Hook method. Define the header of the :ref:`print_layout_doc` in the :ref:`print_layout` :param header: the header object The docHeader() method allows to receive an object called header to which you can append a layout structure made by :meth:`layouts <gnr.core.gnrhtml.GnrHtmlSrc.layout>`, :meth:`rows <gnr.core.gnrhtml.GnrHtmlSrc.row>`, and :meth:`cells <gnr.core.gnrhtml.GnrHtmlSrc.cell>` .. note:: the method is called only if the :ref:`bagtohtml_doc_header_height` has a value different from ``0``""" pass def defineStandardStyles(self): """TODO""" self.body.style(""" .caption{text-align:center; color:gray; font-size:8pt; height:4mm; line-height:4mm; font-weight: normal; } .smallCaption{font-size:7pt; text-align:left; color:gray; text-indent:1mm; width:auto; font-weight: normal; line-height:auto; line-height:3mm; height:3mm;""") self.body.style(""" .extrasmall {font-size:6pt;text-align:left;line-height:3mm;} .textfield {text-indent:0mm;margin:1mm;line-height:3mm} .dotted_bottom {border-bottom:1px dotted gray;} .aligned_right{ text-align:right; margin-right:1.5mm; } .aligned_left{ text-align:left; margin-left:1.5mm; } .aligned_center{ text-align:center; } """)
class Main(BaseResourceMail): batch_prefix = 'mail_tpl' batch_cancellable = True batch_delay = 0.5 batch_immediate = True batch_title = None templates = '' def do(self): self.sendmail_selection() def sendmail_selection(self, thermo_selection=None, thermo_record=None): thermo_s = dict(line_code='selection', message='get_record_caption', tblobj=self.tblobj) thermo_s.update(thermo_selection or {}) thermo_r = dict(line_code='record', message='get_record_caption') thermo_r.update(thermo_record or {}) if isinstance(thermo_s['message'], basestring) and hasattr( self, thermo_s['message']): thermo_s['message'] = getattr(self, thermo_s['message']) if isinstance(thermo_r['message'], basestring) and hasattr( self.htmlMaker, thermo_r['message']): thermo_r['message'] = getattr(self.htmlMaker, thermo_r['message']) if not 'templates' in self.batch_parameters: self.batch_parameters['templates'] = self.templates #CONTROLLARE records = self.get_records() pkeyfield = self.tblobj.pkey if not self.get_selection(): return for record in self.btc.thermo_wrapper(records, maximum=len( self.get_selection()), **thermo_s): self.sendmail_record(record=record, thermo=thermo_r, storagekey=record[pkeyfield]) def pre_process(self): extra_parameters = self.batch_parameters.pop('extra_parameters') self.maintable = extra_parameters['table'] pkg, table = self.maintable.split('.') template_address = extra_parameters[ 'template_address'] or extra_parameters['template_id'] data = self.get_template(template_address) self.compiledTemplate = Bag(data['compiled']) self.mail_pars = Bag(data['metadata.email_compiled']) self.mail_pars['attachments'] = self.mail_pars.pop( 'attachments') if 'attachments' in self.mail_pars else '' self.batch_parameters.setdefault( 'letterhead_id', data.getItem('metadata.default_letterhead')) self.batch_parameters.setdefault('as_pdf', False) self.batch_title = data['summary'] or 'Mail' self.tblobj = self.db.table(self.maintable) self.virtual_columns = self.compiledTemplate.getItem( 'main?virtual_columns') self.mail_preference['html'] = not self.batch_parameters['as_pdf'] self.htmlMaker = TableScriptToHtml(self.page, self.tblobj) def sendmail_record(self, record=None, thermo=None, storagekey=None, **kwargs): record.update(self.batch_parameters) as_pdf = self.batch_parameters['as_pdf'] to_address = templateReplace(self.mail_pars.getItem('to_address', ''), record) subject = templateReplace(self.mail_pars.getItem('subject', ''), record) cc_address = templateReplace(self.mail_pars.getItem('cc_address', ''), record) htmlContent = templateReplace( self.compiledTemplate, record, safeMode=True, noneIsBlank=False, locale=self.page.locale, formats=self.compiledTemplate.getItem('main?formats'), masks=self.compiledTemplate.getItem('main?masks'), localizer=self.page.localizer) result = self.htmlMaker(htmlContent=htmlContent, filename='%s.html' % record['id'], record=record, thermo=thermo, pdf=as_pdf, **self.batch_parameters) if result: attachments = templateReplace( self.mail_pars.getItem('attachments', ''), record) attachments = attachments.split(',') if attachments else [] body = None if as_pdf: attachments.append(result) body = '' else: body = result attachments = attachments or None self.send_one_email(to_address=to_address, cc_address=cc_address, subject=subject, body=body, attachments=attachments, _record_id=record[self.tblobj.pkey]) def table_script_parameters_pane(self, pane, extra_parameters=None, record_count=None, **kwargs): pkg, tbl = extra_parameters['table'].split('.') pane = pane.div(padding='10px', min_height='60px') template_address = extra_parameters[ 'template_address'] or 'adm.userobject.data:%s' % extra_parameters[ 'template_id'] data = self.loadTemplate(template_address, asSource=True)[0] #data,meta = self.db.table('adm.userobject').loadUserObject(pkey=extra_parameters['template_id']) pane.dataFormula('#table_script_runner.dialog_pars.title', 'dlgtitle', dlgtitle='!!%s (%i)' % (data['metadata.summary'] or 'Mail', record_count), _onBuilt=True) fb = pane.formbuilder(cols=1, fld_width='20em', border_spacing='4px') fb.dbSelect(dbtable='adm.htmltemplate', value='^.letterhead_id', lbl='!!Letterhead', hasDownArrow=True) fb.checkbox(value='^.as_pdf', label='!!Send as pdf') fb.dataController( "SET .letterhead_id = default_letterhead || null;", _onBuilt=True, default_letterhead=data.getItem('metadata.default_letterhead') or False, _if='default_letterhead') fb.textbox(value='^.mail_code', lbl='Mail code') if data.getItem('parameters'): parameters = data.getItem('parameters') fielddict = { 'T': 'Textbox', 'L': 'NumberTextBox', 'D': 'DateTextBox', 'B': 'Checkbox', 'N': 'NumberTextBox', 'TL': 'Simpletextarea' } for n in parameters: attr = n.attr values = attr.get('values') mandatory = attr.get('mandatory') == 'T' kwargs = dict(value='^.%s' % attr['code'], lbl=attr['description'] or attr['code'], validate_notnull=mandatory) if values: tag = 'filteringSelect' kwargs['values'] = values else: tag = fielddict[attr.get('fieldtype') or 'T'] if tag == 'Simpletextarea': kwargs['lbl_vertical_align'] = 'top' kwargs['colspan'] = 2 kwargs['tag'] = tag fb.child(**kwargs)
class Main(BaseResourceMail): batch_prefix = 'mail_tpl' batch_cancellable = True batch_delay = 0.5 batch_immediate = True batch_title = None templates = '' def do(self): self.sendmail_selection() def sendmail_selection(self, thermo_selection=None, thermo_record=None): thermo_s = dict(line_code='selection', message='get_record_caption', tblobj=self.tblobj) thermo_s.update(thermo_selection or {}) thermo_r = dict(line_code='record', message='get_record_caption') thermo_r.update(thermo_record or {}) if isinstance(thermo_s['message'], basestring) and hasattr(self, thermo_s['message']): thermo_s['message'] = getattr(self, thermo_s['message']) if isinstance(thermo_r['message'], basestring) and hasattr(self.htmlMaker, thermo_r['message']): thermo_r['message'] = getattr(self.htmlMaker, thermo_r['message']) if not 'templates' in self.batch_parameters: self.batch_parameters['templates'] = self.templates #CONTROLLARE records = self.get_records() pkeyfield = self.tblobj.pkey if not self.get_selection(): return for record in self.btc.thermo_wrapper(records, maximum=len(self.get_selection()), **thermo_s): self.sendmail_record(record=record, thermo=thermo_r, storagekey=record[pkeyfield]) def pre_process(self): extra_parameters = self.batch_parameters.pop('extra_parameters') self.maintable = extra_parameters['table'] pkg,table = self.maintable.split('.') template_address = extra_parameters['template_address'] or extra_parameters['template_id'] data = self.get_template(template_address) self.compiledTemplate = Bag(data['compiled']) self.mail_pars = Bag(data['metadata.email_compiled']) self.mail_pars['attachments'] = self.mail_pars.pop('attachments') if 'attachments' in self.mail_pars else '' self.batch_parameters.setdefault('letterhead_id',data.getItem('metadata.default_letterhead')) self.batch_parameters.setdefault('as_pdf',False) self.batch_title = data['summary'] or 'Mail' self.tblobj = self.db.table(self.maintable) self.virtual_columns = self.compiledTemplate.getItem('main?virtual_columns') self.mail_preference['html'] = not self.batch_parameters['as_pdf'] self.htmlMaker = TableScriptToHtml(self.page,self.tblobj) def sendmail_record(self, record=None, thermo=None, storagekey=None,**kwargs): record.update(self.batch_parameters) as_pdf = self.batch_parameters['as_pdf'] to_address = templateReplace(self.mail_pars.getItem('to_address',''),record) subject = templateReplace(self.mail_pars.getItem('subject',''),record) cc_address = templateReplace(self.mail_pars.getItem('cc_address',''),record) from_address = templateReplace(self.mail_pars.getItem('from_address',''),record) htmlContent=templateReplace(self.compiledTemplate,record, safeMode=True,noneIsBlank=False, locale=self.page.locale, formats=self.compiledTemplate.getItem('main?formats'), masks=self.compiledTemplate.getItem('main?masks'), localizer=self.page.localizer) result = self.htmlMaker(htmlContent=htmlContent, filename='%s.html' %record['id'], record=record, thermo=thermo, pdf=as_pdf, **self.batch_parameters) if result: attachments = templateReplace(self.mail_pars.getItem('attachments',''),record) attachments = attachments.split(',') if attachments else [] body = None if as_pdf: attachments.append(result) body = '' else: body = result attachments = attachments or None self.send_one_email(to_address=to_address,from_address=from_address, cc_address=cc_address, subject=subject,body=body,attachments=attachments,_record_id=record[self.tblobj.pkey]) def table_script_parameters_pane(self,pane,extra_parameters=None,record_count=None,**kwargs): pkg,tbl= extra_parameters['table'].split('.') pane = pane.div(padding='10px',min_height='60px') template_address = extra_parameters['template_address'] or 'adm.userobject.data:%s' %extra_parameters['template_id'] data = self.loadTemplate(template_address,asSource=True)[0] #data,meta = self.db.table('adm.userobject').loadUserObject(pkey=extra_parameters['template_id']) pane.dataFormula('#table_script_runner.dialog_pars.title','dlgtitle', dlgtitle='!!%s (%i)' %(data['metadata.summary'] or 'Mail',record_count),_onBuilt=True) fb = pane.formbuilder(cols=1,fld_width='20em',border_spacing='4px') fb.dbSelect(dbtable='adm.htmltemplate', value='^.letterhead_id',lbl='!!Letterhead',hasDownArrow=True) fb.checkbox(value='^.as_pdf',label='!!Send as pdf') fb.dataController("SET .letterhead_id = default_letterhead || null;",_onBuilt=True, default_letterhead=data.getItem('metadata.default_letterhead') or False,_if='default_letterhead') fb.textbox(value='^.mail_code',lbl='Mail code') if data.getItem('parameters'): parameters = data.getItem('parameters') fielddict = {'T':'Textbox','L':'NumberTextBox','D':'DateTextBox','B':'Checkbox','N':'NumberTextBox', 'TL':'Simpletextarea'} for n in parameters: attr = n.attr values=attr.get('values') mandatory = attr.get('mandatory') == 'T' kwargs = dict(value='^.%s' %attr['code'],lbl=attr['description'] or attr['code'], validate_notnull=mandatory) if values: tag = 'filteringSelect' kwargs['values'] = values else: tag = fielddict[attr.get('fieldtype') or 'T'] if tag == 'Simpletextarea': kwargs['lbl_vertical_align']='top' kwargs['colspan'] = 2 kwargs['tag'] =tag fb.child(**kwargs)
def importMoverLines(self,table=None,objtype=None,pkeys=None): databag = Bag(self.page.site.getStaticPath('user:temp','mover','data','%s_%s.xml' %(table.replace('.','_'),objtype))) tblobj = self.db.table(table) if objtype=='record' else self.db.table('adm.userobject') for pkey in pkeys.keys(): tblobj.insertOrUpdate(databag.getItem(pkey)) self.db.commit()
class Main(BaseResourcePrint): batch_prefix = 'pr_tpl' batch_cancellable = True batch_delay = 0.5 batch_immediate = True batch_title = None print_mode = 'pdf' def pre_process(self): extra_parameters = self.batch_parameters.pop('extra_parameters') self.maintable = extra_parameters['table'] pkg,table = self.maintable.split('.') template_address = extra_parameters['template_address'] or extra_parameters['template_id'] data = self.get_template(template_address) self.compiledTemplate = Bag(data['compiled']) self.batch_parameters.setdefault('letterhead_id',data['metadata.default_letterhead']) self.batch_title = data['summary'] or 'Print' self.tblobj = self.db.table(self.maintable) self.virtual_columns = self.compiledTemplate.getItem('main?virtual_columns') self.htmlMaker = TableScriptToHtml(self.page,self.tblobj) def print_record(self, record=None, thermo=None, storagekey=None,**kwargs): record.update(self.batch_parameters) htmlContent=templateReplace(self.compiledTemplate,record, safeMode=True,noneIsBlank=False, locale=self.page.locale, formats=self.compiledTemplate.getItem('main?formats'), masks=self.compiledTemplate.getItem('main?masks'), dtypes= self.compiledTemplate.getItem('main?dtypes'), localizer=self.page.localizer, urlformatter=self.page.externalUrl) result = self.htmlMaker(htmlContent=htmlContent, filename='%s.html' %record['id'], record=record, thermo=thermo, pdf=self.pdf_make, **self.batch_parameters) if result: self.storeResult(storagekey, result, record, filepath=self.htmlMaker.filepath) def table_script_parameters_pane(self,pane,extra_parameters=None,record_count=None,**kwargs): pkg,tbl= extra_parameters['table'].split('.') pane = pane.div(padding='10px',min_height='60px') template_address = extra_parameters['template_address'] or 'adm.userobject.data:%s' %extra_parameters['template_id'] data = self.loadTemplate(template_address,asSource=True)[0] #data,meta = self.db.table('adm.userobject').loadUserObject(pkey=extra_parameters['template_id']) pane.dataFormula('#table_script_runner.dialog_pars.title','dlgtitle', dlgtitle='!!%s (%i)' %(data['metadata.summary'] or 'Print',record_count),_onBuilt=True) fb = pane.formbuilder(cols=1,fld_width='20em',border_spacing='4px') fb.dbSelect(dbtable='adm.htmltemplate', value='^.letterhead_id',lbl='!!Letterhead',hasDownArrow=True) fb.dataController("SET .letterhead_id = default_letterhead || null;",_onBuilt=True, default_letterhead=data.getItem('metadata.default_letterhead') or False,_if='default_letterhead') if data.getItem('parameters'): parameters = data.getItem('parameters') fielddict = {'T':'Textbox','L':'NumberTextBox','D':'DateTextBox','B':'Checkbox','N':'NumberTextBox', 'TL':'Simpletextarea'} for n in parameters: attr = n.attr values=attr.get('values') mandatory = attr.get('mandatory') == 'T' kwargs = dict(value='^.%s' %attr['code'],lbl=attr['description'] or attr['code'], validate_notnull=mandatory) if values: tag = 'filteringSelect' kwargs['values'] = values else: tag = fielddict[attr.get('fieldtype') or 'T'] if tag == 'Simpletextarea': kwargs['lbl_vertical_align']='top' kwargs['colspan'] = 2 kwargs['tag'] =tag fb.child(**kwargs)
class TestBasicBag(unittest.TestCase): def setUp(self): self.bag = Bag() self.fullbag = Bag( { "office": Bag({"John": Bag(), "Frank": Bag(), "Alexandra": Bag()}), "friends": Bag({"Henry": Bag(), "Fred": Bag()}), "relatives": Bag({"Karla": Bag(), "Albert": Bag()}), } ) def testinit(self): """ this test case check different kinds of bag's instantiation: - from a list of tuples - from a dictionary - empty bag """ firstbag = Bag({"a": 1}) # bag from a dict secondbag = Bag([("a", 1)]) # bag from list of tuple thirdbag = Bag() thirdbag.setItem("a", 1) # empty bag filled bagstring = "0 - (int) a: 1 " # bag as string self.failUnless(firstbag.asString() == secondbag.asString() == thirdbag.asString() == bagstring) def testsetgetItem(self): """ this test case checks the methods setItem and getItem """ self.bag.setItem("a.b.c", 5) self.failUnless(self.bag.getItem("a.b.c") == self.bag["a.b.c"] == 5) self.bag["a.b.c"] = 6 self.failUnless(self.bag.getItem("a.b.c") == self.bag["a.b.c"] == 6) def testindexposition(self): """ this test case checks the method index and the argument "_position" """ self.bag["a.b.c"] = 6 self.bag.addItem("a.b.d", 15) self.failUnless(self.bag.getItem("a.b.#1") == self.bag["a.b.d"] == 15) self.assertEqual(self.bag["a.b"].index("d"), 1) self.bag.setItem("a.b.middle", 10, _position="<d") self.assertEqual(self.bag["a.b"].index("middle"), 1) self.assertEqual(self.bag["a.b"].index("d"), 2) def testgetIndexList(self): il = self.fullbag.getIndexList() self.assertEqual(len(il), 10) def testkeysitemsvalues(self): """ this test case checks the methods -keys -items -values """ self.failUnless(self.fullbag["office"].keys() == self.fullbag["office?"] == ["Frank", "John", "Alexandra"]) self.failUnless( len(self.fullbag["office"].keys()) == len(self.fullbag["office"].values()) == len(self.fullbag["office"].items()) == 3 ) self.assertTrue(self.fullbag["office"].has_key("John")) def testpopin(self): """ this test case checks the method pop and the clause "in" """ self.assertTrue("John" in self.fullbag["office"]) self.fullbag["office.Desmond"] = Bag() d = self.fullbag["office.Desmond"] removed = self.fullbag["office"].pop("#3") self.assertEqual(d, removed) self.assertEqual(self.fullbag["office"].keys(), ["Frank", "John", "Alexandra"]) def testasDict(self): """ this test case checks the method asDict """ d = self.fullbag["office"].asDict() self.assertTrue(isinstance(d, dict)) self.assertEqual(d.keys(), self.fullbag["office?"])
class Main(BaseResourcePrint): batch_prefix = 'pr_tpl' batch_cancellable = True batch_delay = 0.5 batch_immediate = True batch_title = None print_mode = 'pdf' def pre_process(self): extra_parameters = self.batch_parameters.pop('extra_parameters') self.maintable = extra_parameters['table'] pkg, table = self.maintable.split('.') template_address = extra_parameters[ 'template_address'] or extra_parameters['template_id'] data = self.get_template(template_address) self.compiledTemplate = Bag(data['compiled']) self.batch_parameters.setdefault('letterhead_id', data['metadata.default_letterhead']) self.batch_title = data['summary'] or 'Print' self.tblobj = self.db.table(self.maintable) self.virtual_columns = self.compiledTemplate.getItem( 'main?virtual_columns') self.htmlMaker = TableScriptToHtml(self.page, self.tblobj) def print_record(self, record=None, thermo=None, storagekey=None, **kwargs): record.update(self.batch_parameters) htmlContent = templateReplace( self.compiledTemplate, record, safeMode=True, noneIsBlank=False, locale=self.page.locale, formats=self.compiledTemplate.getItem('main?formats'), masks=self.compiledTemplate.getItem('main?masks'), dtypes=self.compiledTemplate.getItem('main?dtypes'), localizer=self.page.localizer, urlformatter=self.page.externalUrl) result = self.htmlMaker(htmlContent=htmlContent, filename='%s.html' % record['id'], record=record, thermo=thermo, pdf=self.pdf_make, **self.batch_parameters) if result: self.storeResult(storagekey, result, record, filepath=self.htmlMaker.filepath) def table_script_parameters_pane(self, pane, extra_parameters=None, record_count=None, **kwargs): pkg, tbl = extra_parameters['table'].split('.') pane = pane.div(padding='10px', min_height='60px') template_address = extra_parameters[ 'template_address'] or 'adm.userobject.data:%s' % extra_parameters[ 'template_id'] data = self.loadTemplate(template_address, asSource=True)[0] #data,meta = self.db.table('adm.userobject').loadUserObject(pkey=extra_parameters['template_id']) pane.dataFormula('#table_script_runner.dialog_pars.title', 'dlgtitle', dlgtitle='!!%s (%i)' % (data['metadata.summary'] or 'Print', record_count), _onBuilt=True) fb = pane.formbuilder(cols=1, fld_width='20em', border_spacing='4px') fb.dbSelect(dbtable='adm.htmltemplate', value='^.letterhead_id', lbl='!!Letterhead', hasDownArrow=True) fb.dataController( "SET .letterhead_id = default_letterhead || null;", _onBuilt=True, default_letterhead=data.getItem('metadata.default_letterhead') or False, _if='default_letterhead') if data.getItem('parameters'): parameters = data.getItem('parameters') fielddict = { 'T': 'Textbox', 'L': 'NumberTextBox', 'D': 'DateTextBox', 'B': 'Checkbox', 'N': 'NumberTextBox', 'TL': 'Simpletextarea' } for n in parameters: attr = n.attr values = attr.get('values') mandatory = attr.get('mandatory') == 'T' kwargs = dict(value='^.%s' % attr['code'], lbl=attr['description'] or attr['code'], validate_notnull=mandatory) if values: tag = 'filteringSelect' kwargs['values'] = values else: tag = fielddict[attr.get('fieldtype') or 'T'] if tag == 'Simpletextarea': kwargs['lbl_vertical_align'] = 'top' kwargs['colspan'] = 2 kwargs['tag'] = tag fb.child(**kwargs)
class BagToHtml(object): """A class that transforms a :ref:`bag` into HTML. It can be used to make a :ref:`print`""" css_requires = '' templates = '' letterhead_id = '' currencyFormat = u'#,###.00' encoding = 'utf-8' page_debug = False page_width = 200 page_height = 280 page_margin_top = 0 page_margin_left = 0 page_margin_right = 0 page_margin_bottom = 0 page_header_height = 0 page_footer_height = 0 page_leftbar_width = 0 page_rightbar_width = 0 print_button = None row_mode = 'value' rows_path = 'rows' doc_header_height = 0 # e.g. 10 doc_footer_height = 0 # e.g. 15 grid_header_height = 0 # e.g. 6.2 grid_footer_height = 0 grid_col_headers = None grid_col_widths = [0, 0, 0] grid_row_height = 5 copies_per_page = 1 copy_extra_height = 0 starting_page_number = 0 body_attributes = None def __init__(self, locale='en', encoding='utf-8', templates=None, templateLoader=None, **kwargs): self.locale = locale self.encoding = encoding self.thermo_kwargs = None self.thermo_wrapper = None if templates: self.templates = templates if templateLoader: self.templateLoader = templateLoader def init(self, *args, **kwargs): """A ``init`` hook method""" pass def outputDocName(self, ext=''): """Set the filename extension and return it :param ext: the filename extension""" return 'temp.%s' % ext def onRecordLoaded(self): """Hook method. Allow to define the query to be executed for the :ref:`print` Example:: def onRecordLoaded(self): where = '$date >= :begin_date AND $date <= :end_date AND doctor_id=:d_id' columns ='''$doctor,$date,$hour,$patient,$performance, @convention_id.code AS convention_code, $amount,$cost,@invoice_id.number AS invoice''' query = self.db.table(self.rows_table).query(columns=columns, where=where, begin_data = self.getData('period.from'), end_data = self.getData('period.to'), d_id=self.record['id']) selection = query.selection() if not selection: return False self.setData('rows',selection.output('grid'))""" pass def orientation(self): """Set the page orientation to 'Landscape' if the :ref:`bagtohtml_page_width` is greater than the :ref:`bagtohtml_page_height`, else set the orientation to 'Portrait'""" if self.page_width > self.page_height: return 'Landscape' else: return 'Portrait' def __call__(self, record=None, filepath=None, folder=None, filename=None, hideTemplate=False, rebuild=True, htmlContent=None, page_debug=None, is_draft=None, **kwargs): """Return the html corresponding to a given record. The html can be loaded from a cached document or created as new if still doesn't exist""" if record is None: record = Bag() self.htmlContent = htmlContent self._data = Bag() self.is_draft = is_draft self.record = record self.setData('record', record) #compatibility for k, v in kwargs.items(): self.setData(k, v) if not filepath: folder = folder or tempfile.mkdtemp() filepath = os.path.join(folder, filename or self.outputDocName(ext='html')) self.filepath = filepath if not rebuild: with open(self.filepath, 'r') as f: result = f.read() return result self.templates = kwargs.pop('templates', self.templates) self.letterhead_id = kwargs.pop('letterhead_id', self.letterhead_id) self.print_button = kwargs.pop('print_button', self.print_button) if self.onRecordLoaded() is False: return False self.showTemplate(hideTemplate is not True) self.htmlTemplate = None self.prepareTemplates() self.page_debug = page_debug or self.page_debug self.builder = GnrHtmlBuilder( page_width=self.page_width, page_height=self.page_height, page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom, page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right, page_debug=self.page_debug, print_button=self.print_button, htmlTemplate=self.htmlTemplate, css_requires=self.get_css_requires(), showTemplateContent=self.showTemplateContent, parent=self) result = self.createHtml(filepath=self.filepath, body_attributes=self.body_attributes) return result def get_css_requires(self): """Get the :ref:`"css_requires" webpage variable <css_requires>` in its string format and return it as a list""" return self.css_requires.split(',') def prepareTemplates(self): """Set the correct value of every measure of the page: height, width, header, footer, margins""" top_layer = Bag() if not self.htmlTemplate: self.htmlTemplate = self.templateLoader( letterhead_id=self.letterhead_id, name=self.templates) if self.htmlTemplate: top_layer = self.htmlTemplate['#%i' % (len(self.htmlTemplate) - 1)] d = self.__dict__ self.page_height = float( d.get('page_height') or top_layer['main.page.height'] or self.page_height) self.page_width = float( d.get('page_width') or top_layer['main.page.width'] or self.page_width) self.page_margin_top = float( d.get('page_margin_top') or top_layer['main.page.top'] or self.page_margin_top) self.page_margin_left = float( d.get('page_margin_left') or top_layer['main.page.left'] or self.page_margin_left) self.page_margin_right = float( d.get('page_margin_right') or top_layer['main.page.right'] or self.page_margin_right) self.page_margin_bottom = float( d.get('page_margin_bottom') or top_layer['main.page.bottom'] or self.page_margin_bottom) self.page_header_height = float( d.get('page_header_height') or top_layer['layout.top?height'] or self.page_header_height) self.page_footer_height = float( d.get('page_footer_height') or top_layer['layout.bottom?height'] or self.page_footer_height) self.page_leftbar_width = float( d.get('page_leftbar_width') or top_layer['layout.left?width'] or self.page_leftbar_width) self.page_rightbar_width = float( d.get('page_rightbar_width') or top_layer['layout.right?width'] or self.page_rightbar_width) def toText(self, obj, locale=None, format=None, mask=None, encoding=None, **kwargs): """TODO :param obj: TODO :param locale: the current locale (e.g: en, en_us, it) :param format: TODO :param mask: TODO :param encoding: the multibyte character encoding you choose""" locale = locale or self.locale encoding = locale or self.encoding return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding, **kwargs) def createHtml(self, filepath=None, body_attributes=None): """TODO :param filepath: the path where html will be saved""" #filepath = filepath or self.filepath self.initializeBuilder(body_attributes=body_attributes) self.main() self.builder.toHtml(filepath=filepath) return self.builder.html def showTemplate(self, value): """TODO :param value: TODO""" self.showTemplateContent = value def setTemplates(self, templates): """Set a template. :param templates: TODO""" self.templates = templates def getTemplates(self, templates): """TODO :param templates: TODO""" return self.templates def initializeBuilder(self, body_attributes=None): """TODO""" self.builder.initializeSrc(body_attributes=body_attributes) self.body = self.builder.body self.getNewPage = self.builder.newPage self.builder.styleForLayout() def getNewPage(self): pass def getData(self, path, default=None): """Make a :meth:`getItem() <gnr.core.gnrbag.Bag.getItem>` on data if ... TODO :param path: the path of data (e.g: ``'period.from'``) :param default: the default return value for a not found item""" wildchars = [] if path[0] in wildchars: value = 'not yet implemented' else: value = self._data.getItem(path, default) return value def setData(self, path, value, **kwargs): """Make a :meth:`setItem() <gnr.core.gnrbag.Bag.setItem>` on data :param path: the path of data (e.g: ``'period.from'``) :param default: the default return value for a not found item""" self._data.setItem(path, value, **kwargs) def onRecordExit(self, recordBag): """Hook method. :param recordBag: a :ref:`bag` that contains the result of the batch""" return def field(self, path, default=None, locale=None, format=None, mask=None, root=None, **kwargs): """TODO :param path: TODO :param default: TODO :param locale: the current locale (e.g: en, en_us, it) :param format: TODO :param mask: TODO :param root: the root of the page. For more information, check the :ref:`webpages_main` documentation section""" if root is None: root = self._data['record'] attr = {} if isinstance(root, Bag): datanode = root.getNode(path) if datanode: value = datanode.value attr = datanode.attr else: value = default else: value = root.get(path) format = format or attr.get('format') mask = mask or attr.get('mask') if value is None: value = default elif isinstance(value, Bag) and not format: return value return self.toText(value, locale, format, mask, self.encoding, **kwargs) def main(self): """It can be overridden""" if self.htmlContent: page = self.getNewPage() page.div("%s::HTML" % self.htmlContent) else: self.mainLoop() def onNewPage(self, page): if self.is_draft: page.div( style= 'position:absolute; top:0; left:0; right:0; bottom:0; z-index:10000', _class='document_draft') def pageCounter(self, mask=None): """Allow to automatically number the pages created in a :ref:`print`. You can choose the format output with the *mask* parameter :param mask: format output of the pageCounter method. By default is ``'%s/%s'`` **Example**: if you print three pages then they will be numbered as `1/3`, `2/3` and `3/3` **Syntax**: You can alternatively set it as ``'%s of %s'``, ``'%s - %s'`` and so on""" mask = mask or '%s/%s' def getPage(currPage=0): result = mask % (currPage + 1 + self.starting_page_number, self.copies[self.copy]['currPage'] + 1 + self.starting_page_number) return result return BagCbResolver(getPage, currPage=self.copies[self.copy]['currPage']) def copyHeight(self): """TODO""" return (self.page_height - self.page_margin_top - self.page_margin_bottom -\ self.page_header_height - self.page_footer_height -\ self.copy_extra_height * (self.copies_per_page - 1)) / self.copies_per_page def copyWidth(self): """TODO""" return (self.page_width - self.page_margin_left - self.page_margin_right -\ self.page_leftbar_width - self.page_rightbar_width) def mainLoop(self): """TODO""" self.copies = [] self.lastPage = False self.defineStandardStyles() self.defineCustomStyles() self.doc_height = self.copyHeight( ) #- self.page_header_height - self.page_footer_height self.grid_height = self.doc_height - self.calcDocHeaderHeight( ) - self.calcDocFooterHeight() self.grid_body_height = float(self.grid_height or 0) - float( self.grid_header_height or 0) - float(self.grid_footer_height or 0) for copy in range(self.copies_per_page): self.copies.append( dict(grid_body_used=self.grid_height, currPage=-1)) lines = self.getData(self.rows_path) if not lines and hasattr(self, 'empty_row'): lines = Bag() lines.setItem('empty', Bag(self.empty_row), **self.empty_row) if lines: if isinstance(lines, Bag): nodes = lines.getNodes() elif hasattr(lines, 'next'): nodes = list(lines) else: nodes = lines lastNode = nodes[-1] if hasattr(self, 'thermo_wrapper') and self.thermo_kwargs: nodes = self.thermo_wrapper(nodes, **self.thermo_kwargs) for rowDataNode in nodes: self.isLastRow = rowDataNode is lastNode self.currRowDataNode = rowDataNode for copy in range(self.copies_per_page): self.onNewRow() self.copy = copy rowheight = self.calcRowHeight() availableSpace = self.grid_height - self.copyValue('grid_body_used') -\ self.calcGridHeaderHeight() - self.calcGridFooterHeight() if rowheight > availableSpace: self._newPage() if not self.rowData: continue row = self.copyValue('body_grid').row(height=rowheight) self.copies[self.copy]['grid_body_used'] = self.copyValue( 'grid_body_used') + rowheight self.currColumn = 0 self.currRow = row self.prepareRow(row) for copy in range(self.copies_per_page): self.copy = copy self._closePage(True) def onNewRow(self): pass def _newPage(self): if self.copyValue('currPage') >= 0: self._closePage() self.copies[self.copy]['currPage'] = self.copyValue('currPage') + 1 self.copies[self.copy]['grid_body_used'] = 0 self._createPage() self._openPage() def _get_rowData(self): if isinstance(self.currRowDataNode, dict) or isinstance( self.currRowDataNode, Bag): return self.currRowDataNode elif self.row_mode == 'attribute': return self.currRowDataNode.attr else: return self.currRowDataNode.value rowData = property(_get_rowData) def rowField(self, path=None, **kwargs): """TODO :param path: TODO""" #if self.row_mode=='attribute': # data = self.currRowDataNode.attr #else: # data = self.currRowDataNode.value return self.field(path, root=self.rowData, **kwargs) def rowCell(self, field=None, value=None, default=None, locale=None, format=None, mask=None, currency=None, white_space='nowrap', **kwargs): """Allow to get data from record. You can use it in the :meth:`prepareRow` method :param field: the name of the table :ref:`column` :param value: TODO :param default: TODO :param locale: the current locale (e.g: en, en_us, it) :param format: the format of the cell (e.g: use ``HH:mm``) :param mask: TODO :param currency: TODO""" if field: if callable(field): value = field() else: value = self.rowField(field, default=default, locale=locale, format=format, mask=mask, currency=currency) if value is not None: #if self.lastPage: # print 'last page' # print self.currColumn # print self.grid_col_widths[self.currColumn] value = self.toText(value, locale, format, mask, self.encoding) self.currRow.cell(value, width=self.grid_col_widths[self.currColumn], overflow='hidden', white_space=white_space, **kwargs) self.currColumn = self.currColumn + 1 return value def _createPage(self): curr_copy = self.copies[self.copy] if self.copy == 0: self.paperPage = self.getNewPage() #self.page_header_height = self.page_header_height or getattr(self.builder,'page_header_height') #self.page_footer_height = self.page_footer_height or getattr(self.builder,'page_footer_height') self.page_layout = self.mainLayout(self.paperPage) #if self.page_header_height: # curr_copy['page_header'] = self.page_layout.row(height=self.page_header_height,lbl_height=4,lbl_class='caption').cell() if self.calcDocHeaderHeight(): curr_copy['doc_header'] = self.page_layout.row( height=self.calcDocHeaderHeight(), lbl_height=4, lbl_class='caption').cell() curr_copy['doc_body'] = self.page_layout.row( height=0, lbl_height=4, lbl_class='caption').cell() if self.calcDocFooterHeight(): curr_copy['doc_footer'] = self.page_layout.row( height=self.doc_footer_height, lbl_height=4, lbl_class='caption').cell() #if self.page_footer_height: # curr_copy['page_footer'] = self.page_layout.row(height=self.page_footer_height,lbl_height=4,lbl_class='caption').cell() def mainLayout(self, page): """Hook method that must be overridden. It gives the :ref:`print_layout_page` object to which you have to append a :meth:`layout <gnr.core.gnrhtml.GnrHtmlSrc.layout>` :param page: the page object""" print 'mainLayout must be overridden' def _openPage(self): #if self.page_header_height: # self.pageHeader(self.copyValue('page_header')) #makeTop if self.doc_header_height: self.docHeader(self.copyValue('doc_header')) self._docBody(self.copyValue('doc_body')) def _closePage(self, lastPage=None): if lastPage: self.lastPage = True self.fillBodyGrid() footer_height = self.calcGridFooterHeight() if footer_height: row = self.copyValue('body_grid').row(height=footer_height) self.currColumn = 0 self.currRow = row self.gridFooter(row) if self.calcDocFooterHeight(): self.docFooter(self.copyValue('doc_footer'), lastPage=lastPage) #if self.page_footer_height: # self.pageFooter(self.copyValue('page_footer'),lastPage=lastPage) def _docBody(self, body): header_height = self.calcGridHeaderHeight() grid = self.gridLayout(body) if header_height: self.gridHeader(grid.row(height=header_height)) self.copies[self.copy]['body_grid'] = grid def gridLayout(self, grid): """Hook method. MANDATORY if you define a :ref:`print_layout_grid` in your :ref:`print`. Through this method you receive the center of the page and you can define the layout of the grid :param grid: the :ref:`print_layout_grid`""" print 'gridLayout must be overridden' def gridHeader(self, row): """It can be overridden :param row: the grid row""" lbl_height = 4 headers = self.grid_col_headers if ':' in headers: headers, lbl_height = headers.split(':') lbl_height = int(lbl_height) for k, lbl in enumerate(self.grid_col_headers.split(',')): style = None if lbl == '|': lbl = '' style = 'border-top:0mm;border-bottom:0mm;' row.cell(lbl=lbl, lbl_height=lbl_height, width=self.grid_col_widths[k], style=style) def gridFooter(self, row): """It can be overridden :param row: the grid row""" return def fillBodyGrid(self): """TODO""" row = self.copyValue('body_grid').row() for w in self.grid_col_widths: row.cell(width=w) def copyValue(self, valuename): """TODO :param valuename: the name of the value to copy""" return self.copies[self.copy][valuename] def calcRowHeight(self): """override for special needs""" return self.grid_row_height def calcGridHeaderHeight(self): """override for special needs""" return self.grid_header_height def calcGridFooterHeight(self): """override for special needs""" return self.grid_footer_height def calcDocHeaderHeight(self): """override for special needs""" return self.doc_header_height def calcDocFooterHeight(self): """override for special needs""" return self.doc_footer_height def defineCustomStyles(self): """override this for custom styles""" pass def docFooter(self, footer, lastPage=None): """Hook method. Define the footer of the :ref:`print_layout_doc` in the :ref:`print_layout` :param footer: the footer object :param lastPage: boolean. More information in the :ref:`lastpage` section .. note:: the method is called only if the :ref:`bagtohtml_doc_footer_height` has a value different from ``0``""" pass def pageFooter(self, footer, lastPage=None): """Hook method. Define the footer of the :ref:`print_layout_page` in the :ref:`print_layout` :param footer: the footer object :param lastPage: boolean. More information in the :ref:`lastpage` section .. note:: the method is called only if the :ref:`bagtohtml_page_footer_height` has a value different from ``0``""" pass def pageHeader(self, header): """Hook method. Define the header of the :ref:`print_layout_page` in the :ref:`print_layout` :param header: the header object .. note:: the method is called only if the :ref:`bagtohtml_page_header_height` has a value different from ``0``""" pass def docHeader(self, header): """Hook method. Define the header of the :ref:`print_layout_doc` in the :ref:`print_layout` :param header: the header object The docHeader() method allows to receive an object called header to which you can append a layout structure made by :meth:`layouts <gnr.core.gnrhtml.GnrHtmlSrc.layout>`, :meth:`rows <gnr.core.gnrhtml.GnrHtmlSrc.row>`, and :meth:`cells <gnr.core.gnrhtml.GnrHtmlSrc.cell>` .. note:: the method is called only if the :ref:`bagtohtml_doc_header_height` has a value different from ``0``""" pass def defineStandardStyles(self): """TODO""" self.body.style(""" .caption{text-align:center; color:gray; font-size:8pt; height:4mm; line-height:4mm; font-weight: normal; } .smallCaption{font-size:7pt; text-align:left; color:gray; text-indent:1mm; width:auto; font-weight: normal; line-height:auto; line-height:3mm; height:3mm;""") self.body.style(""" .extrasmall {font-size:6pt;text-align:left;line-height:3mm;} .textfield {text-indent:0mm;margin:1mm;line-height:3mm} .dotted_bottom {border-bottom:1px dotted gray;} .aligned_right{ text-align:right; margin-right:1.5mm; } .aligned_left{ text-align:left; margin-left:1.5mm; } .aligned_center{ text-align:center; } """)
class BagToHtml(object): """add??? """ templates = '' print_button = None rows_path = 'rows' encoding = 'utf-8' page_debug = False page_width = 200 page_height = 280 page_margin_top = 0 page_margin_left = 0 page_margin_right = 0 page_margin_bottom = 0 currencyFormat = u'#,###.00' #override these lines row_mode = 'value' page_header_height = 0 # page_footer_height = 0 page_leftbar_width = 0 page_rightbar_width = 0 doc_header_height = 0 # eg 10 doc_footer_height = 0 # eg 15 grid_header_height = 0 # eg 6.2 grid_footer_height = 0 grid_col_widths = [0, 0, 0] grid_row_height = 5 copies_per_page = 1 copy_extra_height = 0 starting_page_number = 0 css_requires = '' def __init__(self, locale='en', encoding='utf-8', templates=None, templateLoader=None, **kwargs): self.locale = locale self.encoding = encoding self.thermo_kwargs = None self.thermo_wrapper = None if templates: self.templates = templates if templateLoader: self.templateLoader = templateLoader def init(self, *args, **kwargs): """add???""" pass def outputDocName(self, ext=''): """add??? :param ext: add???. Default value is `` `` """ return 'temp.%s' % ext def onRecordLoaded(self): """override this""" pass def orientation(self): """add??? """ if self.page_width>self.page_height: return 'Landscape' else: return 'Portrait' def __call__(self, record=None, filepath=None, folder=None, filename=None, hideTemplate=False, rebuild=True, htmlContent=None, **kwargs): """Return the html corresponding to a given record. The html can be loaded from a cached document or created if still doesn't exist. """ if record is None: record = Bag() self.htmlContent = htmlContent self._data = Bag() self.record = record self.setData('record', record) #compatibility for k, v in kwargs.items(): self.setData(k, v) if folder and not filepath: filepath = os.path.join(folder, filename or self.outputDocName(ext='html')) self.filepath = filepath if not rebuild: with open(self.filepath, 'r') as f: result = f.read() return result self.templates = kwargs.pop('templates', self.templates) self.print_button = kwargs.pop('print_button', self.print_button) if self.onRecordLoaded() is False: return False self.showTemplate(hideTemplate is not True) self.htmlTemplate = None self.prepareTemplates() self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height, page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom, page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right, page_debug=self.page_debug, print_button=self.print_button, htmlTemplate=self.htmlTemplate, css_requires=self.get_css_requires(), showTemplateContent=self.showTemplateContent) result = self.createHtml(filepath=self.filepath) return result def get_css_requires(self): return self.css_requires.split(',') def prepareTemplates(self): """add???""" if not self.htmlTemplate: self.htmlTemplate = self.templateLoader(self.templates) self.page_height = self.page_height or self.htmlTemplate['main.page.height'] or 280 self.page_width = self.page_width or self.htmlTemplate['main.page.width'] or 200 self.page_header_height = self.page_header_height or self.htmlTemplate['layout.top?height'] or 0 self.page_footer_height = self.page_footer_height or self.htmlTemplate['layout.bottom?height'] or 0 self.page_leftbar_width = self.page_leftbar_width or self.htmlTemplate['layout.left?width'] or 0 self.page_rightbar_width = self.page_leftbar_width or self.htmlTemplate['layout.right?width'] or 0 self.page_margin_top = self.page_margin_top or self.htmlTemplate['main.page.top'] or 0 self.page_margin_left = self.page_margin_left or self.htmlTemplate['main.page.left'] or 0 self.page_margin_right = self.page_margin_right or self.htmlTemplate['main.page.right'] or 0 self.page_margin_bottom = self.page_margin_bottom or self.htmlTemplate['main.page.bottom'] or 0 def toText(self, obj, locale=None, format=None, mask=None, encoding=None, **kwargs): """add??? :param obj: add??? :param locale: add???. Default value is ``None`` :param format: add???. Default value is ``None`` :param mask: add???. Default value is ``None`` :param encoding: The multibyte character encoding you choose. Default value is ``None`` :returns: add??? """ locale = locale or self.locale encoding = locale or self.encoding return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding, **kwargs) def createHtml(self, filepath=None): """add??? :param filepath: add???. Default value is ``None`` :returns: add??? """ #filepath = filepath or self.filepath self.initializeBuilder() self.main() self.builder.toHtml(filepath=filepath) return self.builder.html def showTemplate(self, value): """add??? :param value: add??? :returns: add??? """ self.showTemplateContent = value def setTemplates(self, templates): """add??? :param templates: add??? :returns: add??? """ self.templates = templates def getTemplates(self, templates): """add??? :param templates: add??? :returns: add??? """ return self.templates def initializeBuilder(self): """add???""" self.builder.initializeSrc() self.body = self.builder.body self.getNewPage = self.builder.newPage self.builder.styleForLayout() def getData(self, path, default=None): """add??? :param path: add??? :param default: add???. Default value is ``None`` :returns: add??? """ wildchars = [] if path[0] in wildchars: value = 'not yet implemented' else: value = self._data.getItem(path, default) return value def setData(self, path, value, **kwargs): """add??? :param path: add??? :param value: add??? """ self._data.setItem(path, value, **kwargs) def onRecordExit(self, recordBag): """add??? :param recordBag: add??? """ return def field(self, path, default=None, locale=None, format=None, mask=None, root=None, **kwargs): """add??? :param path: add??? :param default: add???. Default value is ``None`` :param locale: add???. Default value is ``None`` :param format: add???. Default value is ``None`` :param mask: add???. Default value is ``None`` :param root: add???. Default value is ``None`` :returns: add??? """ if root is None: root = self._data['record'] attr = {} if isinstance(root, Bag): datanode = root.getNode(path) if datanode: value = datanode.value attr = datanode.attr else: value = default else: value = root.get(path) if value is None: value = default elif isinstance(value, Bag): return value format = format or attr.get('format') mask = mask or attr.get('mask') return self.toText(value, locale, format, mask, self.encoding, **kwargs) def main(self): """It can be overridden""" if self.htmlContent: page = self.getNewPage() page.div("%s::HTML" % self.htmlContent) else: self.mainLoop() def pageCounter(self, mask=None): """add??? :param mask: add???. Default value is ``None`` """ mask = mask or '%s/%s' def getPage(currPage=0): result = mask % (currPage + 1 + self.starting_page_number, self.copies[self.copy]['currPage'] + 1 + self.starting_page_number) return result return BagCbResolver(getPage, currPage=self.copies[self.copy]['currPage']) def copyHeight(self): """add???""" return (self.page_height - self.page_margin_top - self.page_margin_bottom -\ self.page_header_height - self.page_footer_height -\ self.copy_extra_height * (self.copies_per_page - 1)) / self.copies_per_page def copyWidth(self): """add???""" return (self.page_width - self.page_margin_left - self.page_margin_right -\ self.page_leftbar_width - self.page_rightbar_width) def mainLoop(self): """add???""" self.copies = [] self.lastPage = False self.defineStandardStyles() self.defineCustomStyles() self.doc_height = self.copyHeight() #- self.page_header_height - self.page_footer_height self.grid_height = self.doc_height - self.calcDocHeaderHeight() - self.doc_footer_height self.grid_body_height = self.grid_height - self.grid_header_height - self.grid_footer_height for copy in range(self.copies_per_page): self.copies.append(dict(grid_body_used=self.grid_height, currPage=-1)) lines = self.getData(self.rows_path) if lines: if isinstance(lines, Bag): nodes = lines.getNodes() elif hasattr(lines, 'next'): nodes = list(lines) if hasattr(self, 'thermo_wrapper') and self.thermo_kwargs: nodes = self.thermo_wrapper(nodes, **self.thermo_kwargs) for rowDataNode in nodes: self.currRowDataNode = rowDataNode for copy in range(self.copies_per_page): self.copy = copy rowheight = self.calcRowHeight() availableSpace = self.grid_height - self.copyValue('grid_body_used') -\ self.calcGridHeaderHeight() - self.calcGridFooterHeight() if rowheight > availableSpace: self._newPage() row = self.copyValue('body_grid').row(height=rowheight) self.copies[self.copy]['grid_body_used'] = self.copyValue('grid_body_used') + rowheight self.currColumn = 0 self.currRow = row self.prepareRow(row) for copy in range(self.copies_per_page): self.copy = copy self._closePage(True) def _newPage(self): if self.copyValue('currPage') >= 0: self._closePage() self.copies[self.copy]['currPage'] = self.copyValue('currPage') + 1 self.copies[self.copy]['grid_body_used'] = 0 self._createPage() self._openPage() def _get_rowData(self): if isinstance(self.currRowDataNode, dict): return self.currRowDataNode elif self.row_mode == 'attribute': return self.currRowDataNode.attr else: return self.currRowDataNode.value rowData = property(_get_rowData) def rowField(self, path=None, **kwargs): """add??? :param path: add???. Default value is ``None`` :returns: add??? """ #if self.row_mode=='attribute': # data = self.currRowDataNode.attr #else: # data = self.currRowDataNode.value return self.field(path, root=self.rowData, **kwargs) def rowCell(self, field=None, value=None, default=None, locale=None, format=None, mask=None, currency=None, **kwargs): """add??? :param field: add???. Default value is ``None`` :param value: add???. Default value is ``None`` :param default: add???. Default value is ``None`` :param locale: add???. Default value is ``None`` :param format: add???. Default value is ``None`` :param mask: add???. Default value is ``None`` :param currency: add???. Default value is ``None`` :returns: add??? """ if field: if callable(field): value = field() else: value = self.rowField(field, default=default, locale=locale, format=format, mask=mask, currency=currency) if value is not None: #if self.lastPage: # print 'last page' # print self.currColumn # print self.grid_col_widths[self.currColumn] value = self.toText(value, locale, format, mask, self.encoding) self.currRow.cell(value, width=self.grid_col_widths[self.currColumn], overflow='hidden', white_space='nowrap', **kwargs) self.currColumn = self.currColumn + 1 return value def _createPage(self): curr_copy = self.copies[self.copy] if self.copy == 0: self.paperPage = self.getNewPage() self.page_layout = self.mainLayout(self.paperPage) #if self.page_header_height: # curr_copy['page_header'] = self.page_layout.row(height=self.page_header_height,lbl_height=4,lbl_class='caption').cell() if self.doc_header_height: curr_copy['doc_header'] = self.page_layout.row(height=self.calcDocHeaderHeight(), lbl_height=4, lbl_class='caption').cell() curr_copy['doc_body'] = self.page_layout.row(height=0, lbl_height=4, lbl_class='caption').cell() if self.doc_footer_height: curr_copy['doc_footer'] = self.page_layout.row(height=self.doc_footer_height, lbl_height=4, lbl_class='caption').cell() #if self.page_footer_height: # curr_copy['page_footer'] = self.page_layout.row(height=self.page_footer_height,lbl_height=4,lbl_class='caption').cell() def mainLayout(self, page): """must be overridden :param page: add??? """ pass def _openPage(self): #if self.page_header_height: # self.pageHeader(self.copyValue('page_header')) #makeTop if self.doc_header_height: self.docHeader(self.copyValue('doc_header')) self._docBody(self.copyValue('doc_body')) def _closePage(self, lastPage=None): if lastPage: self.lastPage = True self.fillBodyGrid() footer_height = self.calcGridFooterHeight() if footer_height: row = self.copyValue('body_grid').row(height=footer_height) self.currColumn = 0 self.currRow = row self.gridFooter(row) if self.doc_footer_height: self.docFooter(self.copyValue('doc_footer'), lastPage=lastPage) #if self.page_footer_height: # self.pageFooter(self.copyValue('page_footer'),lastPage=lastPage) def _docBody(self, body): header_height = self.calcGridHeaderHeight() grid = self.gridLayout(body) if header_height: self.gridHeader(grid.row(height=header_height)) self.copies[self.copy]['body_grid'] = grid def gridLayout(self, grid): """It must be overridden :param grid: add??? """ print 'gridLayout must be overridden' def gridHeader(self, row): """It can be overridden :param row: add??? """ lbl_height = 4 headers = self.grid_col_headers if ':' in headers: headers, lbl_height = headers.split(':') lbl_height = int(lbl_height) for k, lbl in enumerate(self.grid_col_headers.split(',')): style = None if lbl == '|': lbl = '' style = 'border-top:0mm;border-bottom:0mm;' row.cell(lbl=lbl, lbl_height=lbl_height, width=self.grid_col_widths[k], style=style) def gridFooter(self, row): """It can be overridden :param row: add??? """ print 'gridFooter must be overridden' def fillBodyGrid(self): """add??? """ row = self.copyValue('body_grid').row() for w in self.grid_col_widths: row.cell(width=w) def copyValue(self, valuename): """add??? :param valuename: add??? """ return self.copies[self.copy][valuename] def calcRowHeight(self): """override for special needs :returns: add??? """ return self.grid_row_height def calcGridHeaderHeight(self): """override for special needs :returns: add??? """ return self.grid_header_height def calcGridFooterHeight(self): """override for special needs :returns: add??? """ return self.grid_footer_height def calcDocHeaderHeight(self): """override for special needs :returns: add??? """ return self.doc_header_height def defineCustomStyles(self): """override this for custom styles :returns: add??? """ pass def docFooter(self, footer, lastPage=None): """add??? :param footer: add??? :param lastPage: add???. Default value is ``None`` """ pass def pageFooter(self, footer, lastPage=None): """add??? :param footer: add??? :param lastPage: add???. Default value is ``None`` """ pass def pageHeader(self, header): """add??? :param header: add??? """ pass def docHeader(self, header): """add??? :param header: add??? """ pass def defineStandardStyles(self): """add??? """ self.body.style(""" .caption{text-align:center; color:gray; font-size:8pt; height:4mm; line-height:4mm; font-weight: normal; } .smallCaption{font-size:7pt; text-align:left; color:gray; text-indent:1mm; width:auto; font-weight: normal; line-height:auto; line-height:3mm; height:3mm;""") self.body.style(""" .extrasmall {font-size:6pt;text-align:left;line-height:3mm;} .textfield {text-indent:0mm;margin:1mm;line-height:3mm} .dotted_bottom {border-bottom:1px dotted gray;} .aligned_right{ text-align:right; margin-right:1mm; } .aligned_left{ text-align:left; margin-left:1mm; } .aligned_center{ text-align:center; } """)
class TestBasicBag(unittest.TestCase): def setUp(self): self.bag = Bag() self.fullbag = Bag({ 'office': Bag({ 'John': Bag(), 'Frank': Bag(), 'Alexandra': Bag() }), 'friends': Bag({ 'Henry': Bag(), 'Fred': Bag() }), 'relatives': Bag({ 'Karla': Bag(), 'Albert': Bag() }) }) def testinit(self): """ this test case check different kinds of bag's instantiation: - from a list of tuples - from a dictionary - empty bag """ firstbag = Bag({'a': 1}) #bag from a dict secondbag = Bag([('a', 1)]) #bag from list of tuple thirdbag = Bag() thirdbag.setItem('a', 1) #empty bag filled bagstring = '0 - (int) a: 1 ' #bag as string self.failUnless(firstbag.asString() == secondbag.asString() == thirdbag.asString() == bagstring) def testsetgetItem(self): """ this test case checks the methods setItem and getItem """ self.bag.setItem('a.b.c', 5) self.failUnless(self.bag.getItem('a.b.c') == self.bag['a.b.c'] == 5) self.bag['a.b.c'] = 6 self.failUnless(self.bag.getItem('a.b.c') == self.bag['a.b.c'] == 6) def testindexposition(self): """ this test case checks the method index and the argument "_position" """ self.bag['a.b.c'] = 6 self.bag.addItem('a.b.d', 15) self.failUnless(self.bag.getItem('a.b.#1') == self.bag['a.b.d'] == 15) self.assertEqual(self.bag['a.b'].index('d'), 1) self.bag.setItem('a.b.middle', 10, _position='<d') self.assertEqual(self.bag['a.b'].index('middle'), 1) self.assertEqual(self.bag['a.b'].index('d'), 2) def testgetIndexList(self): il = self.fullbag.getIndexList() self.assertEqual(len(il), 10) def testkeysitemsvalues(self): """ this test case checks the methods -keys -items -values """ self.failUnless(self.fullbag['office'].keys() == self. fullbag['office?'] == ['Frank', 'John', 'Alexandra']) self.failUnless( len(self.fullbag['office'].keys()) == len( self.fullbag['office'].values()) == len( self.fullbag['office'].items()) == 3) self.assertTrue(self.fullbag['office'].has_key('John')) def testpopin(self): """ this test case checks the method pop and the clause "in" """ self.assertTrue('John' in self.fullbag['office']) self.fullbag['office.Desmond'] = Bag() d = self.fullbag['office.Desmond'] removed = self.fullbag['office'].pop('#3') self.assertEqual(d, removed) self.assertEqual(self.fullbag['office'].keys(), ['Frank', 'John', 'Alexandra']) def testasDict(self): """ this test case checks the method asDict """ d = self.fullbag['office'].asDict() self.assertTrue(isinstance(d, dict)) self.assertEqual(d.keys(), self.fullbag['office?'])