logparse / formatting.pyon commit update setup.py to python 3, implement config file settings (0765fe0)
   1#
   2#   format.py
   3#   
   4#   This file contains global functions for formatting and printing data. This
   5#   file should be imported into individual log-parsing scripts located in
   6#   logs/*. Data is all formatted in HTML. Writing to disk and/or emailng data
   7#   is left to __main__.py.
   8#
   9
  10import os
  11import re
  12import locale
  13from string import Template
  14
  15import logparse
  16from . import interface, util, config
  17
  18import logging
  19logger = logging.getLogger(__name__)
  20
  21locale.setlocale(locale.LC_ALL, '') # inherit system locale
  22#DEG = "°".encode('unicode_escape')
  23DEG = u'\N{DEGREE SIGN}'
  24CEL = "C"
  25TIMEFMT = "%X"
  26DATEFMT = "%x"
  27
  28def init_varfilter():
  29    global varfilter
  30    global varpattern
  31    global varsubst
  32    varfilter = {"$title$": config.prefs['title'], "$date$": interface.start.strftime(DATEFMT),"$time$": interface.start.strftime(TIMEFMT), "$hostname$": util.hostname(config.prefs['hostname-path']), "$version$": logparse.__version__, "$css$": os.path.relpath(config.prefs['css'], os.path.dirname(config.prefs['output']))}
  33    varfilter = dict((re.escape(k), v) for k, v in varfilter.items())
  34    varpattern = re.compile("|".join(varfilter.keys()))
  35    varsubst = dict(title=config.prefs['title'], date=interface.start.strftime(DATEFMT), time=interface.start.strftime(TIMEFMT), hostname=util.hostname(config.prefs['hostname-path']), version=logparse.__version__, css=os.path.relpath(config.prefs['css'], os.path.dirname(config.prefs['output'])))
  36
  37def writetitle(title):  # write title for a section
  38    if (title == '' or '\n' in title):
  39        logger.error("Invalid title")
  40        raise ValueError 
  41    logger.debug("Writing title for " + title)
  42    return tag('h2', 0, title)
  43
  44def opentag(tag, block = 0, id = None, cl = None):   # write html opening tag
  45    output = ""
  46    if (block):
  47        output += '\n'
  48    output += '<' + tag
  49    if (id != None):
  50        output += " id='" + id + "'"
  51    if (cl != None):
  52        output += " class='" + cl + "'"
  53    output += '>'
  54    if (block):
  55        output += '\n'
  56    return output
  57
  58def closetag(tag, block = 0):  # write html closing tag
  59    if (block == 0):
  60        return "</" + tag + ">"
  61    else:
  62        return "\n</" + tag + ">\n"
  63
  64def tag(tag, block = 0, content = ""):  # write html opening tag, content, and html closing tag
  65    o = opentag(tag, block)
  66    c = closetag(tag, block)
  67    return o + content + c
  68
  69def header(template):   # return a parsed html header from file
  70#    try:
  71#        copyfile(config['css'], config['dest'] + '/' + os.path.basename(config['css']))
  72#        logger.debug("copied main.css")
  73#    except Exception as e:
  74#        logger.warning("could not copy main.css - " + str(e))
  75    init_varfilter()
  76    headercontent = Template(open(template, 'r').read())
  77    return headercontent.safe_substitute(varsubst)
  78
  79def orderbyfreq(l):     # order a list by the frequency of its elements and remove duplicates
  80    temp_l = l[:]
  81    l = list(set(l))
  82    l = [[i, temp_l.count(i)] for i in l]   # add count of each element
  83    l.sort(key=lambda x:temp_l.count(x[0])) # sort by count
  84    l = [i[0] + ' (' + str(i[1]) + ')' for i in l]  # put element and count into string
  85    l = l[::-1]     # reverse
  86    return l
  87
  88def addtag(l, tag):  # add prefix and suffix tags to each item in a list
  89    l2 = ['<' + tag + '>' + i + '</' + tag + '>' for i in l]
  90    return l2
  91
  92def truncl(input, limit):      # truncate list
  93    if (len(input) > limit):
  94        more = str(len(input) - limit)
  95        output = input[:limit]
  96        output.append("+ " + more + " more")
  97        return(output)
  98    else:
  99        return(input)
 100
 101def plural(noun, quantity): # return "1 noun" or "n nouns"
 102    if (quantity == 1):
 103        return(str(quantity) + " " + noun)
 104    else:
 105        return(str(quantity) + " " + noun + "s")
 106
 107def parsesize(num, suffix='B'):     # return human-readable size from number of bytes
 108    for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
 109        if abs(num) < 1024.0:
 110            return "%3.1f %s%s" % (num, unit, suffix)
 111        num /= 1024.0
 112    return "%.1f%s%s" % (num, 'Yi', suffix)
 113
 114def fsubject(template): # Replace variables in the title template provided in config
 115    r = varpattern.sub(lambda m: varfilter[re.escape(m.group(0))], template)
 116    logger.debug("Returning subject line " + r)
 117    return r
 118
 119def writedata(subtitle, data = None):   # write title and data
 120    if (subtitle == ""):
 121        logger.warning("No subtitle provided.. skipping section")
 122        return
 123
 124    if (data == None or len(data) == 0):
 125        logger.debug("No data provided.. just printing subtitle")
 126        return tag('p', 0, subtitle)
 127    else:
 128        logger.debug("Received data " + str(data))
 129        subtitle += ':'
 130        if (len(data) == 1):
 131            return tag('p', 0, subtitle + ' ' + data[0])
 132        else:
 133            output = ""
 134            output += tag('p', 0, subtitle)
 135            output += opentag('ul', 1)
 136            for datum in data:
 137                output += tag('li', 0, datum)
 138            output += closetag('ul', 1)
 139            return output
 140