# -*- coding: utf-8 -*- # # Copyright Grégory Soutadé 2015 # This file is part of iwla # iwla is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # iwla is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with iwla. If not, see . # import os import codecs import time import logging # # Create output HTML files # # Just for detection def _(name): pass _('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July') _('August'), _('September'), _('October'), _('November'), _('December') del _ class DisplayHTMLRaw(object): def __init__(self, iwla, html=u''): self.iwla = iwla self.html = html def setRawHTML(self, html): self.html = html def _buildHTML(self): pass def _build(self, f, html): if html: f.write(html) def build(self, f, filters=None): if filters: self.filter(filters) self._buildHTML() self._build(f, self.html) def _filter(self, function, **kwargs): pass def filter(self, filters): for (args, function) in filters: self._filter(function, **args) def getTitle(self): return '' class DisplayHTMLBlock(DisplayHTMLRaw): def __init__(self, iwla, title=''): super(DisplayHTMLBlock, self).__init__(iwla, html='') self.title = title self.cssclass = u'iwla_block' self.title_cssclass = u'iwla_block_title' self.value_cssclass = u'iwla_block_value' def getTitle(self): return self.title def setTitle(self, value): self.title = value def setCSSClass(self, cssclass): self.cssclass = cssclass def setTitleCSSClass(self, cssclass): self.title_cssclass = cssclass def setValueCSSClass(self, cssclass): self.value_cssclass = cssclass def _buildHTML(self): html = u'
' % (self.cssclass) if self.title: html += u'
%s
' % (self.title_cssclass, self.title) html += u'
%s
' % (self.value_cssclass, self.html) html += u'
' self.html = html class DisplayHTMLBlockTable(DisplayHTMLBlock): def __init__(self, iwla, title, cols, human_readable_cols=None): super(DisplayHTMLBlockTable, self).__init__(iwla=iwla, title=title) self.cols = listToStr(cols) self.rows = [] self.cols_cssclasses = [u''] * len(cols) self.rows_cssclasses = [] self.table_css = u'iwla_table' self.human_readable_cols = human_readable_cols or [] def appendRow(self, row): self.rows.append(listToStr(row)) self.rows_cssclasses.append([u''] * len(row)) def insertCol(self, col_number, col_title='', col_css_class=''): self.cols.insert(col_number, col_title) for r in self.rows: r.insert(col_number, u'') for r in self.rows_cssclasses: v = r[0] # If all cells have the same CSS class, set it for cur_value in r: if v != cur_value: v = None break v = v or u'' r.insert(col_number, v) self.cols_cssclasses.insert(col_number, col_css_class) def getNbRows(self): return len(self.rows) def getNbCols(self): return len(self.cols) def getCellValue(self, row, col): if row < 0 or col < 0 or\ row >= len(self.rows) or col >= len(self.cols): raise ValueError('Invalid indices %d,%d' % (row, col)) return self.rows[row][col] def setCellValue(self, row, col, value): if row < 0 or col < 0 or\ row >= len(self.rows) or col >= len(self.cols): raise ValueError('Invalid indices %d,%d' % (row, col)) self.rows[row][col] = value def setCellCSSClass(self, row, col, value): if row < 0 or col < 0 or\ row >= len(self.rows) or col >= len(self.cols): raise ValueError('Invalid indices %d,%d' % (row, col)) self.rows_cssclasses[row][col] = value def getCellCSSClass(self, row, col): if row < 0 or col < 0 or\ row >= len(self.rows) or col >= len(self.cols): raise ValueError('Invalid indices %d,%d' % (row, col)) return self.rows_cssclasses[row][col] def getColCSSClass(self, col): if col < 0 or col >= len(self.cols): raise ValueError('Invalid indice %d' % (col)) return self.cols_cssclasses[col] def setRowCSSClass(self, row, value): if row < 0 or row >= len(self.rows): raise ValueError('Invalid indice %d' % (row)) self.rows_cssclasses[row] = [value] * len(self.rows_cssclasses[row]) def setColCSSClass(self, col, value): if col < 0 or col >= len(self.cols): raise ValueError('Invalid indice %d' % (col)) self.cols_cssclasses[col] = value def setColsCSSClass(self, values): if len(values) != len(self.cols): raise ValueError('Invalid values size') self.cols_cssclasses = listToStr(values) def computeRatio(self, column, column_insertion=None): if column_insertion is None: column_insertion = column+1 total = 0 for r in self.rows: if r[column]: total += int(r[column]) self.insertCol(column_insertion, self.iwla._('Ratio'), u'iwla_hit') for (index, r) in enumerate(self.rows): val = r[column] and int(r[column]) or 0 self.setCellValue(index, column_insertion, '%.1f%%' % (float(val*100)/float(total))) def _filter(self, function, column, args): target_col = None for col in range(0, len(self.cols)): if self.cols[col] == column: target_col = col break if target_col is None: return for row in self.rows: res = function(row[target_col], **args) if res: row[target_col] = res def _buildHTML(self): style = u'' if self.table_css: style = u' class="%s"' % (self.table_css) html = u'' % (style) if self.cols: html += u'' for i in range (0, len(self.cols)): title = self.cols[i] style = self.getColCSSClass(i) if style: style = u' class="%s"' % (style) html += u'%s' % (style, title) html += u'' for i in range(0, len(self.rows)): row = self.rows[i] html += u'' for j in range(0, len(row)): v = row[j] if j in self.human_readable_cols: v = bytesToStr(v) style = self.getCellCSSClass(i, j) if style: style = u' class="%s"' % (style) html += u'%s' % (style, v) html += u'' html += u'' self.html += html super(DisplayHTMLBlockTable, self)._buildHTML() class DisplayHTMLBlockTableWithGraph(DisplayHTMLBlockTable): def __init__(self, iwla, title, cols, short_titles=None, nb_valid_rows=0, graph_cols=None, human_readable_cols=None): super(DisplayHTMLBlockTableWithGraph, self).__init__(iwla=iwla, title=title, cols=cols, human_readable_cols=human_readable_cols) self.short_titles = short_titles or [] self.short_titles = listToStr(self.short_titles) self.nb_valid_rows = nb_valid_rows self.icon_path = self.iwla.getConfValue('icon_path', '/') self.maxes = [0] * len(cols) self.table_graph_css = u'iwla_graph_table' self.td_img_css = u'iwla_td_img' self.graph_cols = graph_cols or [] def appendShortTitle(self, short_title): self.short_titles.append(short_title) def setShortTitle(self, short_titles): self.short_titles = listToStr(short_titles) def setNbValidRows(self, nb_valid_rows): self.nb_valid_rows = nb_valid_rows def _computeMax(self): for i in range(0, self.nb_valid_rows): row = self.rows[i] for j in range(1, len(row)): if type(row[j]) != int: continue if row[j] > self.maxes[j]: self.maxes[j] = row[j] def _getIconFromStyle(self, style): if style.startswith(u'iwla_page'): icon = u'vp.png' elif style.startswith(u'iwla_hit'): icon = u'vh.png' elif style.startswith(u'iwla_bandwidth'): icon = u'vk.png' elif style.startswith(u'iwla_visitor'): icon = u'vu.png' elif style.startswith(u'iwla_visit'): icon = u'vv.png' else: return '' return u'/%s/other/%s' % (self.icon_path, icon) def _buildHTML(self): self._computeMax() style = u'' if self.table_graph_css: style = u' class="%s"' % (self.table_graph_css) html = u'' % (style) html += u'' for i in range(0, self.nb_valid_rows): row = self.rows[i] css = u'' if self.td_img_css: css=u' class="%s"' % (self.td_img_css) html += u'' % (css) for j in self.graph_cols: style = self.getColCSSClass(j) icon = self._getIconFromStyle(style) if not icon: continue if style: style = u' class="%s"' % (style) alt = u'%s: %s' % (row[j], self.cols[j]) if self.maxes[j]: height = int((self.rows[i][j] * 100) / self.maxes[j]) or 1 else: height = 1 html += u'' % (style, icon, height, alt, alt) html += u'' html += u'' html += u'' for i in range(0, len(self.short_titles)): style = self.getCellCSSClass(i, 0) if style: style = u' class="%s"' % (style) html += u'%s' % (style, self.short_titles[i]) html += u'' html += u'' self.html += html super(DisplayHTMLBlockTableWithGraph, self)._buildHTML() class DisplayHTMLPage(object): def __init__(self, iwla, title, filename, css_path): self.iwla = iwla self.title = title self.filename = filename self.blocks = [] self.css_path = listToStr(css_path) self.logger = logging.getLogger(self.__class__.__name__) def getFilename(self): return self.filename; def getBlock(self, title): for b in self.blocks: if title == b.getTitle(): return b return None def getAllBlocks(self): return self.blocks def appendBlock(self, block): self.blocks.append(block) def build(self, root, displayVersion=True, filters=None): filename = os.path.join(root, self.filename) base = os.path.dirname(filename) if not os.path.exists(base): os.makedirs(base) self.logger.debug('Write %s' % (filename)) if self.iwla.dry_run: return f = codecs.open(filename, 'w', 'utf-8') f.write(u'') f.write(u'') f.write(u'') f.write(u'') f.write(u'') for css in self.css_path: f.write(u'' % (css)) if self.title: f.write(u'%s' % (self.title)) f.write(u'') for block in self.blocks: block.build(f, filters=filters) if displayVersion: f.write(u'
Generated by IWLA %s
' % ("http://indefero.soutade.fr/p/iwla", self.iwla.getVersion())) f.write(u'') f.close() class DisplayHTMLBuild(object): def __init__(self, iwla): self.iwla = iwla self.filters = [] self.clear() def clear(self): self.pages = [] def createPage(self, *args): return DisplayHTMLPage(self.iwla, *args) def createBlock(self, _class, *args): return _class(self.iwla, *args) def getPage(self, filename): for page in self.pages: if page.getFilename() == filename: return page return None def getAllPages(self): return self.pages def addPage(self, page): self.pages.append(page) def build(self, root): if not self.iwla.dry_run: display_root = self.iwla.getConfValue('DISPLAY_ROOT', '') if not os.path.exists(display_root): os.makedirs(display_root) for res_path in self.iwla.getResourcesPath(): target = os.path.abspath(res_path) link_name = os.path.join(display_root, res_path) if not os.path.exists(link_name): os.symlink(target, link_name) for page in self.pages: page.build(root, filters=self.filters) def addColumnFilter(self, column, function, args): self.filters.append(({'column':column, 'args':args}, function)) # # Global functions # def bytesToStr(_bytes): suffixes = [u'', u' kB', u' MB', u' GB', u' TB'] for i in range(0, len(suffixes)): if _bytes < 1024: break _bytes /= 1024.0 if i: return '%.02f%s' % (_bytes, suffixes[i]) else: return '%d%s' % (_bytes, suffixes[i]) def _toStr(v): return v if type(v) != unicode: return unicode(v) else: return v def listToStr(l): return l #map(lambda v : _toStr(v), l) def generateHTMLLink(url, name=None, max_length=100, prefix=u'http'): url = url if not name: name = url if not url.startswith(prefix): url = u'%s://%s' % (prefix, url) return u'%s' % (url, name[:max_length]) def createCurTitle(iwla, title): title = iwla._(title) month_name = time.strftime(u'%B', iwla.getCurTime()) year = time.strftime(u'%Y', iwla.getCurTime()) title += u' - %s %s' % (iwla._(month_name), year) domain_name = iwla.getConfValue('domain_name', '') if domain_name: title += u' - %s' % (domain_name) return title