# Richard Darst, June 2009
###
# Copyright (c) 2009, Richard Darst
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import os
import re
import time
import writers
#from writers import html, rst
import itertools
def inbase(i, chars='abcdefghijklmnopqrstuvwxyz', place=0):
"""Converts an integer into a postfix in base 26 using ascii chars.
This is used to make a unique postfix for ReStructured Text URL
references, which must be unique. (Yes, this is over-engineering,
but keeps it short and nicely arranged, and I want practice
writing recursive functions.)
"""
div, mod = divmod(i, len(chars)**(place+1))
if div == 0:
return chars[mod]
else:
return inbase2(div, chars=chars, place=place+1)+chars[mod]
#
# These are objects which we can add to the meeting minutes. Mainly
# they exist to aid in HTML-formatting.
#
class _BaseItem(object):
itemtype = None
starthtml = ''
endhtml = ''
startrst = ''
endrst = ''
starttext = ''
endtext = ''
startmw = ''
endmw = ''
def get_replacements(self, M, escapewith):
replacements = { }
for name in dir(self):
if name[0] == "_": continue
replacements[name] = getattr(self, name)
replacements['nick'] = escapewith(replacements['nick'])
replacements['link'] = self.logURL(M)
for key in ('line', 'prefix', 'suffix', 'topic'):
if key in replacements:
replacements[key] = escapewith(replacements[key])
if 'url' in replacements:
replacements['url_quoteescaped'] = \
escapewith(self.url.replace('"', "%22"))
return replacements
def template(self, M, escapewith):
template = { }
for k,v in self.get_replacements(M, escapewith).iteritems():
if k not in ('itemtype', 'line', 'topic',
'url', 'url_quoteescaped',
'nick', 'time', 'link', 'anchor'):
continue
template[k] = v
return template
def makeRSTref(self, M):
if self.nick[-1] == '_':
rstref = rstref_orig = "%s%s"%(self.nick, self.time)
else:
rstref = rstref_orig = "%s-%s"%(self.nick, self.time)
count = 0
while rstref in M.rst_refs:
rstref = rstref_orig + inbase(count)
count += 1
link = self.logURL(M)
M.rst_urls.append(".. _%s: %s"%(rstref, link+"#"+self.anchor))
M.rst_refs[rstref] = True
return rstref
@property
def anchor(self):
return 'l-'+str(self.linenum)
def logURL(self, M):
return M.config.basename+'.log.html'
class Topic(_BaseItem):
itemtype = 'TOPIC'
html_template = """
%(time)s |
%(starthtml)sTopic: %(topic)s%(endhtml)s |
"""
#html2_template = ("""%(starthtml)s%(topic)s%(endhtml)s """
# """(%(nick)s, %(time)s)""")
html2_template = ("""%(starthtml)s%(topic)s%(endhtml)s """
""""""
"""(%(nick)s, """
"""%(time)s)"""
"""""")
rst_template = """%(startrst)s%(topic)s%(endrst)s (%(rstref)s_)"""
text_template = """%(starttext)s%(topic)s%(endtext)s (%(nick)s, %(time)s)"""
mw_template = """%(startmw)s%(topic)s%(endmw)s (%(nick)s, %(time)s)"""
startrst = '**'
endrst = '**'
startmw = "'''"
endmw = "'''"
starthtml = ''
endhtml = ''
def __init__(self, nick, line, linenum, time_):
self.nick = nick ; self.topic = line ; self.linenum = linenum
self.time = time.strftime("%H:%M:%S", time_)
def _htmlrepl(self, M):
repl = self.get_replacements(M, escapewith=writers.html)
repl['link'] = self.logURL(M)
return repl
def html(self, M):
return self.html_template%self._htmlrepl(M)
def html2(self, M):
return self.html2_template%self._htmlrepl(M)
def rst(self, M):
self.rstref = self.makeRSTref(M)
repl = self.get_replacements(M, escapewith=writers.rst)
if repl['topic']=='': repl['topic']=' '
repl['link'] = self.logURL(M)
return self.rst_template%repl
def text(self, M):
repl = self.get_replacements(M, escapewith=writers.text)
repl['link'] = self.logURL(M)
return self.text_template%repl
def mw(self, M):
repl = self.get_replacements(M, escapewith=writers.mw)
return self.mw_template%repl
class GenericItem(_BaseItem):
itemtype = ''
html_template = """%(time)s |
%(itemtype)s | %(nick)s | %(starthtml)s%(line)s%(endhtml)s |
"""
#html2_template = ("""%(itemtype)s: %(starthtml)s%(line)s%(endhtml)s """
# """(%(nick)s, %(time)s)""")
html2_template = ("""%(itemtype)s: """
""""""
"""%(starthtml)s%(line)s%(endhtml)s """
""""""
"""(%(nick)s, """
"""%(time)s)"""
"""""")
rst_template = """*%(itemtype)s*: %(startrst)s%(line)s%(endrst)s (%(rstref)s_)"""
text_template = """%(itemtype)s: %(starttext)s%(line)s%(endtext)s (%(nick)s, %(time)s)"""
mw_template = """''%(itemtype)s:'' %(startmw)s%(line)s%(endmw)s (%(nick)s, %(time)s)"""
def __init__(self, nick, line, linenum, time_):
self.nick = nick ; self.line = line ; self.linenum = linenum
self.time = time.strftime("%H:%M:%S", time_)
def _htmlrepl(self, M):
repl = self.get_replacements(M, escapewith=writers.html)
repl['link'] = self.logURL(M)
return repl
def html(self, M):
return self.html_template%self._htmlrepl(M)
def html2(self, M):
return self.html2_template%self._htmlrepl(M)
def rst(self, M):
self.rstref = self.makeRSTref(M)
repl = self.get_replacements(M, escapewith=writers.rst)
repl['link'] = self.logURL(M)
return self.rst_template%repl
def text(self, M):
repl = self.get_replacements(M, escapewith=writers.text)
repl['link'] = self.logURL(M)
return self.text_template%repl
def mw(self, M):
repl = self.get_replacements(M, escapewith=writers.mw)
return self.mw_template%repl
class Info(GenericItem):
itemtype = 'INFO'
html2_template = (""""""
"""%(starthtml)s%(line)s%(endhtml)s """
""""""
"""(%(nick)s, """
"""%(time)s)"""
"""""")
rst_template = """%(startrst)s%(line)s%(endrst)s (%(rstref)s_)"""
text_template = """%(starttext)s%(line)s%(endtext)s (%(nick)s, %(time)s)"""
mw_template = """%(startmw)s%(line)s%(endmw)s (%(nick)s, %(time)s)"""
class Idea(GenericItem):
itemtype = 'IDEA'
class Agreed(GenericItem):
itemtype = 'AGREED'
class Action(GenericItem):
itemtype = 'ACTION'
class Help(GenericItem):
itemtype = 'HELP'
class Accepted(GenericItem):
itemtype = 'ACCEPTED'
starthtml = ''
endhtml = ''
class Rejected(GenericItem):
itemtype = 'REJECTED'
starthtml = ''
endhtml = ''
class Link(_BaseItem):
itemtype = 'LINK'
html_template = """%(time)s |
%(itemtype)s | %(nick)s | %(starthtml)s%(prefix)s%(url_readable)s%(suffix)s%(endhtml)s |
"""
html2_template = ("""%(starthtml)s%(prefix)s%(url_readable)s%(suffix)s%(endhtml)s """
""""""
"""(%(nick)s, """
"""%(time)s)"""
"""""")
rst_template = """*%(itemtype)s*: %(startrst)s%(prefix)s%(url)s%(suffix)s%(endrst)s (%(rstref)s_)"""
text_template = """%(itemtype)s: %(starttext)s%(prefix)s%(url)s%(suffix)s%(endtext)s (%(nick)s, %(time)s)"""
mw_template = """''%(itemtype)s:'' %(startmw)s%(prefix)s%(url)s%(suffix)s%(endmw)s (%(nick)s, %(time)s)"""
def __init__(self, nick, line, linenum, time_, M):
self.nick = nick ; self.linenum = linenum
self.time = time.strftime("%H:%M:%S", time_)
self.line = line
protocols = M.config.UrlProtocols
protocols = '|'.join(re.escape(p) for p in protocols)
protocols = '(?:'+protocols+')'
# This is gross.
# (.*?) - any prefix, non-greedy
# (%s//[^\s]+ - protocol://... until the next space
# (?