[bin] job.py: if the specified user does not exist in the DB, try with a user named 'admin'; [gen] Calendar: allow to insert additional, custom (XHTML or textual) info in any cell of the calendar, via new attribute Calendar.additionalInfo; [pod] some code refactoring; xhtml2odt: allow, when converting tables, to take into account attributes 'width' of tds; bugfix when converting 'href' attrs of 'a' tags.
This commit is contained in:
parent
ba148c51aa
commit
caca61516f
10 changed files with 133 additions and 60 deletions
|
@ -19,6 +19,7 @@
|
|||
# ------------------------------------------------------------------------------
|
||||
import time
|
||||
from appy.shared.utils import Traceback
|
||||
from appy.shared.xml_parser import escapeXhtml
|
||||
|
||||
# Some POD-specific constants --------------------------------------------------
|
||||
XHTML_HEADINGS = ('h1', 'h2', 'h3', 'h4', 'h5', 'h6')
|
||||
|
@ -27,8 +28,6 @@ XHTML_PARAGRAPH_TAGS = XHTML_HEADINGS + XHTML_LISTS + ('p',)
|
|||
XHTML_PARAGRAPH_TAGS_NO_LISTS = XHTML_HEADINGS + ('p',)
|
||||
XHTML_INNER_TAGS = ('b', 'i', 'u', 'em')
|
||||
XHTML_UNSTYLABLE_TAGS = XHTML_LISTS + ('li', 'a')
|
||||
XML_SPECIAL_CHARS = {'<': '<', '>': '>', '&': '&', '"': '"',
|
||||
"'": '''}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class PodError(Exception):
|
||||
|
@ -83,17 +82,6 @@ class PodError(Exception):
|
|||
buffer.write('</%s>' % withinElement.OD.elem)
|
||||
dump = staticmethod(dump)
|
||||
|
||||
def convertToXhtml(s):
|
||||
'''Produces the XHTML-friendly version of p_s.'''
|
||||
res = ''
|
||||
for c in s:
|
||||
if XML_SPECIAL_CHARS.has_key(c):
|
||||
res += XML_SPECIAL_CHARS[c]
|
||||
elif c == '\n':
|
||||
res += '<br/>'
|
||||
elif c == '\r':
|
||||
pass
|
||||
else:
|
||||
res += c
|
||||
return res
|
||||
# XXX To remove, present for backward compatibility only.
|
||||
convertToXhtml = escapeXhtml
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
import re
|
||||
|
||||
from xml.sax.saxutils import quoteattr
|
||||
from appy.pod import PodError, XML_SPECIAL_CHARS
|
||||
from appy.shared.xml_parser import xmlPrologue, escapeXml
|
||||
from appy.pod import PodError
|
||||
from appy.pod.elements import *
|
||||
from appy.pod.actions import IfAction, ElseAction, ForAction, VariableAction, \
|
||||
NullAction
|
||||
from appy.shared import xmlPrologue
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class ParsingError(Exception): pass
|
||||
|
@ -157,11 +157,7 @@ class Buffer:
|
|||
|
||||
def dumpContent(self, content):
|
||||
'''Dumps string p_content into the buffer.'''
|
||||
for c in content:
|
||||
if XML_SPECIAL_CHARS.has_key(c):
|
||||
self.write(XML_SPECIAL_CHARS[c])
|
||||
else:
|
||||
self.write(c)
|
||||
self.write(escapeXml(content))
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
class FileBuffer(Buffer):
|
||||
|
|
|
@ -10,8 +10,9 @@ class OdtTable:
|
|||
tns = 'table:'
|
||||
txns = 'text:'
|
||||
|
||||
def __init__(self, name, paraStyle, cellStyle, nbOfCols,
|
||||
paraHeaderStyle=None, cellHeaderStyle=None, html=False):
|
||||
def __init__(self, name, paraStyle='podTablePara', cellStyle='podTableCell',
|
||||
nbOfCols=1, paraHeaderStyle=None, cellHeaderStyle=None,
|
||||
html=False):
|
||||
# An ODT table must have a name. In the case of an HTML table, p_name
|
||||
# represents the CSS class for the whole table.
|
||||
self.name = name
|
||||
|
@ -24,7 +25,7 @@ class OdtTable:
|
|||
# The default style of every paragraph within a header cell
|
||||
self.paraHeaderStyle = paraHeaderStyle or paraStyle
|
||||
# The default style of every header cell
|
||||
self.cellHeaderStyle = cellHeaderStyle or cellStyle
|
||||
self.cellHeaderStyle = cellHeaderStyle or 'podTableHeaderCell'
|
||||
# The buffer where the resulting table will be rendered
|
||||
self.res = ''
|
||||
# Do we need to generate an HTML table instead of an ODT table ?
|
||||
|
|
|
@ -21,9 +21,9 @@ import os, os.path, sys, zipfile, re, shutil
|
|||
import appy.shared.test
|
||||
from appy.shared.test import TesterError
|
||||
from appy.shared.utils import FolderDeleter
|
||||
from appy.shared.xml_parser import escapeXml
|
||||
from appy.pod.odf_parser import OdfEnvironment, OdfParser
|
||||
from appy.pod.renderer import Renderer
|
||||
from appy.pod import XML_SPECIAL_CHARS
|
||||
|
||||
# TesterError-related constants ------------------------------------------------
|
||||
TEMPLATE_NOT_FOUND = 'Template file "%s" was not found.'
|
||||
|
@ -70,12 +70,7 @@ class AnnotationsRemover(OdfParser):
|
|||
self.res += '</%s>' % elem
|
||||
def characters(self, content):
|
||||
e = OdfParser.characters(self, content)
|
||||
if not self.ignore:
|
||||
for c in content:
|
||||
if XML_SPECIAL_CHARS.has_key(c):
|
||||
self.res += XML_SPECIAL_CHARS[c]
|
||||
else:
|
||||
self.res += c
|
||||
if not self.ignore: self.res += escapeXml(content)
|
||||
def getResult(self):
|
||||
return self.res
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
# ------------------------------------------------------------------------------
|
||||
import xml.sax, time, random
|
||||
from appy.shared.xml_parser import XmlEnvironment, XmlParser
|
||||
from appy.shared.xml_parser import XmlEnvironment, XmlParser, escapeXml
|
||||
from appy.pod.odf_parser import OdfEnvironment
|
||||
from appy.pod.styles_manager import Style
|
||||
from appy.pod import *
|
||||
|
@ -235,6 +235,10 @@ class HtmlTable:
|
|||
# The following list stores, for every column, the size of the biggest
|
||||
# content of all its cells.
|
||||
self.columnContentSizes = []
|
||||
# The following list stores, for every column, its width, if specified.
|
||||
# If widths are found, self.columnContentSizes will not be used:
|
||||
# self.columnWidths will be used instead.
|
||||
self.columnWidths = []
|
||||
|
||||
def computeColumnStyles(self, renderer):
|
||||
'''Once the table has been completely parsed, self.columnContentSizes
|
||||
|
@ -242,22 +246,34 @@ class HtmlTable:
|
|||
of every column and create the corresponding style declarations, in
|
||||
p_renderer.dynamicStyles.'''
|
||||
total = 65000.0 # A number representing the total width of the table
|
||||
# Ensure first that self.columnContentSizes is correct
|
||||
if (len(self.columnContentSizes) != self.nbOfColumns) or \
|
||||
(None in self.columnContentSizes):
|
||||
# There was a problem while parsing the table. Set every column
|
||||
# with the same width.
|
||||
widths = [int(total/self.nbOfColumns)] * self.nbOfColumns
|
||||
# Use (a) self.columnWidths if complete, or
|
||||
# (b) self.columnContentSizes if complete, or
|
||||
# (c) a fixed width else.
|
||||
if self.columnWidths and (len(self.columnWidths) == self.nbOfColumns) \
|
||||
and (None not in self.columnWidths):
|
||||
# Use self.columnWidths
|
||||
toUse = self.columnWidths
|
||||
# Use self.columnContentSizes if complete
|
||||
elif (len(self.columnContentSizes) == self.nbOfColumns) and \
|
||||
(None not in self.columnContentSizes):
|
||||
# Use self.columnContentSizes
|
||||
toUse = self.columnContentSizes
|
||||
else:
|
||||
toUse = None
|
||||
if toUse:
|
||||
widths = []
|
||||
# Compute the sum of all column content sizes
|
||||
contentTotal = 0
|
||||
for size in self.columnContentSizes: contentTotal += size
|
||||
for size in toUse: contentTotal += size
|
||||
contentTotal = float(contentTotal)
|
||||
for size in self.columnContentSizes:
|
||||
for size in toUse:
|
||||
width = int((size/contentTotal) * total)
|
||||
widths.append(width)
|
||||
# Compute style declatation corresponding to every column.
|
||||
else:
|
||||
# There was a problem while parsing the table. Set every column
|
||||
# with the same width.
|
||||
widths = [int(total/self.nbOfColumns)] * self.nbOfColumns
|
||||
# Compute style declaration corresponding to every column.
|
||||
s = self.styleNs
|
||||
i = 0
|
||||
for width in widths:
|
||||
|
@ -321,14 +337,10 @@ class XhtmlEnvironment(XmlEnvironment):
|
|||
currentElem.addInnerParagraph(self)
|
||||
# Dump and reinitialize the current content
|
||||
content = self.currentContent.strip('\n\t')
|
||||
# We remove leading and trailing carriage returns, but not
|
||||
# whitespace because whitespace may be part of the text to dump.
|
||||
contentSize = len(content)
|
||||
for c in content:
|
||||
# We remove leading and trailing carriage returns, but not
|
||||
# whitespace because whitespace may be part of the text to dump.
|
||||
if XML_SPECIAL_CHARS.has_key(c):
|
||||
self.dumpString(XML_SPECIAL_CHARS[c])
|
||||
else:
|
||||
self.dumpString(c)
|
||||
self.dumpString(escapeXml(content))
|
||||
self.currentContent = u''
|
||||
# If we are within a table cell, update the total size of cell content.
|
||||
if self.currentTables and self.currentTables[-1].inCell:
|
||||
|
@ -444,6 +456,16 @@ class XhtmlEnvironment(XmlEnvironment):
|
|||
# If we are in the first row of a table, update columns count
|
||||
if not table.firstRowParsed:
|
||||
table.nbOfColumns += colspan
|
||||
if attrs.has_key('width') and (colspan == 1):
|
||||
# Get the width, keep figures only.
|
||||
width = ''
|
||||
for c in attrs['width']:
|
||||
if c.isdigit(): width += c
|
||||
width = int(width)
|
||||
# Ensure self.columnWidths is long enough
|
||||
while (len(table.columnWidths)-1) < table.cellIndex:
|
||||
table.columnWidths.append(None)
|
||||
table.columnWidths[table.cellIndex] = width
|
||||
return currentElem
|
||||
|
||||
def onElementEnd(self, elem):
|
||||
|
@ -525,7 +547,8 @@ class XhtmlParser(XmlParser):
|
|||
elif elem == 'a':
|
||||
e.dumpString('<%s %s:type="simple"' % (odfTag, e.linkNs))
|
||||
if attrs.has_key('href'):
|
||||
e.dumpString(' %s:href="%s"' % (e.linkNs, attrs['href']))
|
||||
e.dumpString(' %s:href="%s"' % (e.linkNs,
|
||||
escapeXml(attrs['href'])))
|
||||
e.dumpString('>')
|
||||
elif elem in XHTML_LISTS:
|
||||
prologue = ''
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue