logparse / formatting.pyon commit major rewrite: segregate into modules and upgrade to Python 3 (4944c22)
   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
  13
  14from .config import prefs
  15#import util
  16#import interface
  17import logparse
  18from . import interface, util
  19
  20import logging
  21logger = logging.getLogger(__name__)
  22
  23locale.setlocale(locale.LC_ALL, '') # inherit system locale
  24#DEG = "°".encode('unicode_escape')
  25DEG = u'\N{DEGREE SIGN}'
  26CEL = "C"
  27TIMEFMT = "%X"
  28DATEFMT = "%x"
  29
  30def init_varfilter():
  31    global varfilter
  32    global varpattern
  33    varfilter = {"$title$": prefs['title'], "$date$": interface.start.strftime(DATEFMT),"$time$": interface.start.strftime(TIMEFMT), "$hostname$": util.hostname(prefs['hostname-path']), "$version$": logparse.__version__, "$css$": os.path.relpath(prefs['css'], os.path.dirname(prefs['output']))}
  34    varfilter = dict((re.escape(k), v) for k, v in varfilter.items())
  35    varpattern = re.compile("|".join(varfilter.keys()))
  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 = open(template, 'r').read()
  77    headercontent = varpattern.sub(lambda m: varfilter[re.escape(m.group(0))], headercontent)
  78    return headercontent
  79
  80def orderbyfreq(l):     # order a list by the frequency of its elements and remove duplicates
  81    temp_l = l[:]
  82    l = list(set(l))
  83    l = [[i, temp_l.count(i)] for i in l]   # add count of each element
  84    l.sort(key=lambda x:temp_l.count(x[0])) # sort by count
  85    l = [i[0] + ' (' + str(i[1]) + ')' for i in l]  # put element and count into string
  86    l = l[::-1]     # reverse
  87    return l
  88
  89def addtag(l, tag):  # add prefix and suffix tags to each item in a list
  90    l2 = ['<' + tag + '>' + i + '</' + tag + '>' for i in l]
  91    return l2
  92
  93def truncl(input, limit):      # truncate list
  94    if (len(input) > limit):
  95        more = str(len(input) - limit)
  96        output = input[:limit]
  97        output.append("+ " + more + " more")
  98        return(output)
  99    else:
 100        return(input)
 101
 102def plural(noun, quantity): # return "1 noun" or "n nouns"
 103    if (quantity == 1):
 104        return(str(quantity) + " " + noun)
 105    else:
 106        return(str(quantity) + " " + noun + "s")
 107
 108def parsesize(num, suffix='B'):     # return human-readable size from number of bytes
 109    for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
 110        if abs(num) < 1024.0:
 111            return "%3.1f %s%s" % (num, unit, suffix)
 112        num /= 1024.0
 113    return "%.1f%s%s" % (num, 'Yi', suffix)
 114
 115def fsubject(template): # Replace variables in the title template provided in config
 116    r = varpattern.sub(lambda m: varfilter[re.escape(m.group(0))], template)
 117    logger.debug("Returning subject line " + r)
 118    return r
 119
 120def writedata(subtitle, data = None):   # write title and data
 121    if (subtitle == ""):
 122        logger.warning("No subtitle provided.. skipping section")
 123        return
 124
 125    if (data == None or len(data) == 0):
 126        logger.debug("No data provided.. just printing subtitle")
 127        return tag('p', 0, subtitle)
 128    else:
 129        logger.debug("Received data " + str(data))
 130        subtitle += ':'
 131        if (len(data) == 1):
 132            return tag('p', 0, subtitle + ' ' + data[0])
 133        else:
 134            output = ""
 135            output += tag('p', 0, subtitle)
 136            output += opentag('ul', 1)
 137            for datum in data:
 138                output += tag('li', 0, datum)
 139            output += closetag('ul', 1)
 140            return output
 141