Skip to content

Commit

Permalink
- Added inFill property to <linePlot> which will fill the are…
Browse files Browse the repository at this point in the history
…a below

  the line makign it effectively an area plot.

- Added ability to specify the ``labelTextFormat`` property of ``<xValueAxis>``
  and ``<yValueAxis>`` to be a reference to a function via a Python path.

- Added an example from Stack Overflow that exercises the new features. See
  ``tag0linePlot.rml``.

- Remove Python 3.6 support and add 3.8.
  • Loading branch information
strichter committed Mar 27, 2020
1 parent 7b2b993 commit e1f77b4
Show file tree
Hide file tree
Showing 12 changed files with 1,647 additions and 2,150 deletions.
15 changes: 12 additions & 3 deletions CHANGES.rst
Expand Up @@ -2,10 +2,19 @@
CHANGES
=======

3.9.2 (unreleased)
------------------
3.10.0 (unreleased)
-------------------

- Added ``inFill`` property to ``<linePlot>`` which will fill the area below
the line makign it effectively an area plot.

- Added ability to specify the ``labelTextFormat`` property of ``<xValueAxis>``
and ``<yValueAxis>`` to be a reference to a function via a Python path.

- Added an example from Stack Overflow that exercises the new features. See
``tag0linePlot.rml``.

- Nothing changed yet.
- Remove Python 3.6 support and add 3.8.


3.9.1 (2019-10-04)
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -29,7 +29,7 @@ def read(*rnames):

setup (
name="z3c.rml",
version='3.9.2.dev0',
version='3.10.0.dev0',
author="Stephan Richter and the Zope Community",
author_email="zope-dev@zope.org",
description="An alternative implementation of RML",
Expand All @@ -48,8 +48,8 @@ def read(*rnames):
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: Implementation :: CPython',
'Natural Language :: English',
'Operating System :: OS Independent'],
Expand Down
38 changes: 37 additions & 1 deletion src/z3c/rml/attr.py
Expand Up @@ -253,6 +253,7 @@ def fromUnicode(self, ustr):
numbers.append((value, value+1))
return numbers


class Choice(BaseChoice):
"""A choice of several values. The values are always case-insensitive."""

Expand Down Expand Up @@ -365,10 +366,44 @@ def fromUnicode(self, value):
return normalized


class ObjectRef(Text):
"""This field will return a Python object.
The value is a Python path to the object which is being resolved. The
sysntax is expected to be ``<path.to.module>.<name>``.
"""
pythonPath = re.compile('^([A-z_][0-9A-z_.]*)\.([A-z_][0-9A-z_]*)$')

def __init__(self, doNotResolve=False, *args, **kw):
super(ObjectRef, self).__init__(*args, **kw)
self.doNotResolve = doNotResolve

def fromUnicode(self, value):
result = self.pythonPath.match(value)
if result is None:
raise ValueError(
'The Python path you specified is incorrect. %s' %(
getFileInfo(self.context)))
if self.doNotResolve:
return value
modulePath, objectName = result.groups()
try:
module = import_module(modulePath)
except ImportError:
raise ValueError(
'The module you specified was not found: %s' % modulePath)
try:
object = getattr(module, objectName)
except AttributeError:
raise ValueError(
'The object you specified was not found: %s' % objectName)
return object


class File(Text):
"""This field will return a file object.
The value itself can eith be be a relative or absolute path. Additionally
The value itself can either be a relative or absolute path. Additionally
the following syntax is supported: [path.to.python.mpackage]/path/to/file
"""
packageExtract = re.compile('^\[([0-9A-z_.]*)\]/(.*)$')
Expand Down Expand Up @@ -667,6 +702,7 @@ def get(self):
text = text[text.find('>')+1:text.rfind('<')]
return text


class XMLContent(RawXMLContent):
"""Same as 'RawXMLContent', except that the whitespace is normalized."""

Expand Down
20 changes: 18 additions & 2 deletions src/z3c/rml/chart.py
Expand Up @@ -646,9 +646,17 @@ class IValueAxis(IAxis):
description=u'The maximum number of ticks to be shown.',
required=False)

labelTextFormat = attr.String(
labelTextFormat = attr.Combination(
title=u'Label Text Format',
description=u'Formatting string for axis labels.',
description=(
u'Formatting string or Python path to formatting function for '
u'axis labels.'),
value_types=(
# Python path to function.
attr.ObjectRef(),
# Formatting String.
attr.String(),
),
required=False)

labelTextPostFormat = attr.Text(
Expand Down Expand Up @@ -1451,8 +1459,16 @@ class ILinePlot(IChart):
description=u'When true, connect all data points with lines.',
required=False)

inFill = attr.Boolean(
title=u'Name',
description=(
u'Flag indicating whether the line plot should be filled, '
u'in other words converted to an area chart.'),
required=False)

class LinePlot(Chart):
signature = ILinePlot
attrMapping = {'inFill': '_inFill'}

factories = Chart.factories.copy()
factories.update({
Expand Down
6 changes: 4 additions & 2 deletions src/z3c/rml/dtd.py
Expand Up @@ -74,11 +74,13 @@ def generateElement(name, signature, seen):
text += '\n'
# DTD does not support redefinition of an element type or have context
# specific elements.
if name in seen:
if (name, signature) in seen:
text = '\n<!--' + text + '-->\n'
seen.append(name)
seen.append((name, signature))
# Walk through all sub-elements, creating the DTD entries for them.
for occurence in signature.queryTaggedValue('directives', ()):
if (occurence.tag, occurence.signature) in seen:
continue
text += generateElement(occurence.tag, occurence.signature, seen)
return text

Expand Down
15 changes: 9 additions & 6 deletions src/z3c/rml/reference.py
Expand Up @@ -131,7 +131,7 @@ def formatCombination(field):
attr.TextNodeSequence: formatSequence,
attr.TextNodeGrid: formatGrid}

def processSignature(name, signature, examples, directives=None):
def processSignature(name, signature, queue, examples, directives=None):
if directives is None:
directives = {}
# Process this directive
Expand Down Expand Up @@ -188,10 +188,10 @@ def processSignature(name, signature, examples, directives=None):
})
info['sub-directives'] = subs
directives[signature] = info
# Process Children
for occurence in signature.queryTaggedValue('directives', ()):
processSignature(occurence.tag, occurence.signature,
examples, directives)

# Process Children
for occurence in signature.queryTaggedValue('directives', ()):
queue.append((occurence.tag, occurence.signature))


def extractExamples(directory):
Expand Down Expand Up @@ -237,7 +237,10 @@ def main(outPath=None):
template = pagetemplate.RMLPageTemplateFile('reference.pt')

directives = {}
processSignature('document', document.IDocument, examples, directives)
queue = [('document', document.IDocument)]
while queue:
tag, sig = queue.pop()
processSignature(tag, sig, queue, examples, directives)
directives = sorted(directives.values(), key=lambda d: d['name'])

pdf = template(
Expand Down
Binary file modified src/z3c/rml/rml-reference.pdf
Binary file not shown.

0 comments on commit e1f77b4

Please sign in to comment.