diff --git a/src/z3c/rml/attr.py b/src/z3c/rml/attr.py index e09d440..f67b7ce 100644 --- a/src/z3c/rml/attr.py +++ b/src/z3c/rml/attr.py @@ -17,6 +17,7 @@ """ __docformat__ = "reStructuredText" import cStringIO +import os import re import reportlab import reportlab.lib.colors @@ -164,17 +165,35 @@ def convert(self, value, context=None): class Image(Text): - open = urllib.urlopen + open = staticmethod(urllib.urlopen) + packageExtract = re.compile('^\[([0-9A-z_.]*)\]/(.*)$') def __init__(self, name=None, default=DEFAULT, onlyOpen=False): super(Image, self).__init__(name, default) self.onlyOpen = onlyOpen def convert(self, value, context=None): + # Check whether the value is of the form: + # []/rel/path/image.gif" + if value.startswith('['): + result = self.packageExtract.match(value) + if result is None: + raise ValueError( + 'The package-path-pair you specified was incorrect') + modulepath, path = result.groups() + module = __import__(modulepath, {}, {}, (modulepath)) + value = os.path.join(os.path.dirname(module.__file__), path) + # Open/Download the file fileObj = self.open(value) if self.onlyOpen: return fileObj - return reportlab.lib.utils.ImageReader(fileObj) + # ImageReader wants to be able to seek, but URL info objects can only + # be read, so we make a string IO object out of it + sio = cStringIO.StringIO() + sio.write(fileObj.read()) + fileObj.close() + sio.seek(0) + return reportlab.lib.utils.ImageReader(sio) class Color(Text): @@ -184,12 +203,12 @@ def convert(self, value, context=None): if value in ALL_COLORS: return ALL_COLORS[value] # Decimal triplet - rgb = value.split(',') + rgb = Sequence(valueType=Float(), length=3).convert(value) if len(rgb) == 3: - return (float(num) for num in rgb) + return [float(num) for num in rgb] # Hexdecimal triplet if value.startswith('#'): - return (float(int(value[i:i+1], 16)) for i in range(1, 7, 2)) + return [float(int(value[i:i+1], 16)) for i in range(1, 7, 2)] raise ValueError('%r not a valid color.' %value) @@ -267,6 +286,8 @@ def __init__(self): super(TextNode, self).__init__('TEXT') def get(self, element, default=DEFAULT, context=None): + if element.text is None: + return u'' return unicode(element.text).strip() class FirstLevelTextNode(TextNode): diff --git a/src/z3c/rml/canvas.py b/src/z3c/rml/canvas.py index 659d0ef..6174e46 100644 --- a/src/z3c/rml/canvas.py +++ b/src/z3c/rml/canvas.py @@ -247,9 +247,8 @@ def process(self): if subElement.tail is not None: self.processPoints(subElement.tail) - if kw.get('close', False): + if kw.pop('close', False): self.path.close() - del kw['close'] self.context.drawPath(self.path, **kw) diff --git a/src/z3c/rml/chart.py b/src/z3c/rml/chart.py index 2987d84..2aca97a 100644 --- a/src/z3c/rml/chart.py +++ b/src/z3c/rml/chart.py @@ -267,7 +267,7 @@ class ValueAxis(Axis): attr.Bool('forceZero'), # TODO: Support 'near' attr.Measurement('minimumTickSpacing'), attr.Int('maximumTicks'), - attr.Text('labelTextFormat'), + attr.Attribute('labelTextFormat'), attr.Text('labelTextPostFormat'), attr.Float('labelTextScale'), attr.Float('valueMin'), diff --git a/src/z3c/rml/rml2pdf.py b/src/z3c/rml/rml2pdf.py index 825c5a5..f120bb5 100644 --- a/src/z3c/rml/rml2pdf.py +++ b/src/z3c/rml/rml2pdf.py @@ -16,6 +16,7 @@ $Id$ """ __docformat__ = "reStructuredText" +import cStringIO import os import sys import zope.interface @@ -25,6 +26,15 @@ zope.interface.moduleProvides(interfaces.IRML2PDF) +def parseString(xml): + root = etree.fromstring(xml) + doc = document.Document(root) + output = cStringIO.StringIO() + doc.process(output) + output.seek(0) + return output + + def go(xmlInputName, outputFileName=None, outDir=None, dtdDir=None): if dtdDir is not None: sys.stderr.write('The ``dtdDir`` option is not yet supported.')