Commits

Manfred Moitzi committed f97dc24

release 0.2.0 alpha

  • Participants
  • Parent commits d14bce3
  • Tags 0.2.0

Comments (0)

Files changed (25)

 NEWS
 ====
 
-Version 0.2.0 - xxx
+Version 0.2.0 - 24 October 2010
   * alpha version
   * validator rewritten as validator2.py
   * debug and profile options separated for each drawing object
   * important change: create objects with factory functions of the Drawing class: drawing.<svg-elementname>(...)
+  * added mixins for setting stroke and fill properties
   * new elements:
     - Hyperlink <a>
     - Image

File doc/classes/defs.rst

     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG attributes
 --------------
 

File doc/classes/group.rst

     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG attributes
 --------------
 

File doc/classes/hyperlink.rst

     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG attributes
 --------------
 

File doc/classes/mixins.rst

    * http://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty
    * http://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty
 
-.. automethod:: svgwrite.mixins.Presentation.dasharray(definition=None, offset=None)
+.. automethod:: svgwrite.mixins.Presentation.dasharray(dasharray=None, offset=None)
 
 .. seealso::
 
-   * http://www.w3.org/TR/SVG11/painting.html#StrokeArrayProperty
+   * http://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty
    * http://www.w3.org/TR/SVG11/painting.html#StrokeDashoffsetProperty
 
-.. automethod:: svgwrite.mixins.Presentation.viewport_fill(color=None, opacity=None)
+:class:`MediaGroup` mixin
+===========================
 
-   only SVG 1.2 Tiny
+.. autoclass:: svgwrite.mixins.MediaGroup
+
+   SVG Tiny 1.2
+
+   valid for SVG Elements: animation, audio, desc, image, metadata, title, video
+
+Methods
+-------
+
+.. automethod:: svgwrite.mixins.MediaGroup.viewport_fill(color=None, opacity=None)
 
 .. seealso::
 

File doc/classes/path.rst

 --------------------
 
 :class:`svgwrite.interface.ITransform`
+
     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 Path Commands
 -------------
 

File doc/classes/shapes.rst

 ~~~~~~~~~~~~~~~~~~~~
 
 :class:`svgwrite.interface.ITransform`
+
     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
 
+Used Mixins
+~~~~~~~~~~~
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 Supported SVG attributes
 ~~~~~~~~~~~~~~~~~~~~~~~~
 

File doc/classes/svg.rst

 :class:`svgwrite.interface.IViewBox`
     :meth:`viewbox`, :meth:`stretch`, :meth:`fit`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
+
 SVG Attributes
 --------------
 

File doc/classes/symbol.rst

 :class:`svgwrite.interface.IViewBox`
     :meth:`viewbox`, :meth:`stretch`, :meth:`fit`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG attributes
 --------------
 

File doc/classes/text.rst

 --------------------
 
 :class:`svgwrite.interface.ITransform`
+
     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 :class:`TSpan` objects
 ======================
 
 
 .. automethod:: svgwrite.text.TSpan.__init__(text, insert=None, x=[], y=[], dx=[], dy=[], rotate=[], attribs=None, **extra)
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
+
 .. _TSpan-SVG-Attributes:
 
 SVG Attributes
 
 .. automethod:: svgwrite.text.TRef.set_href(element)
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG Attributes
 --------------
 
 
 .. automethod:: svgwrite.text.TextPath.__init__(path, text, startOffset=None, method='align', spacing='exact', attribs=None, **extra)
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG Attributes
 --------------
 
 :class:`svgwrite.interface.ITransform`
     :meth:`translate`, :meth:`rotate`, :meth:`scale`, :meth:`skewX`,
     :meth:`skewY`, :meth:`matrix`, :meth:`rev`, :meth:`del_transform`
+
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`

File doc/classes/use.rst

 :class:`svgwrite.interface.IXLink`
     :meth:`set_href`
 
+Used Mixins
+-----------
+
+:class:`svgwrite.mixins.Presentation`
+
+    :meth:`fill`, :meth:`stroke`, :meth:`dasharray`
+
 SVG Attributes
 --------------
 

File doc/overview.rst

 
    classes/interface
 
+Mixins
+------
+
+.. toctree::
+   :maxdepth: 1
+
+   classes/mixins
+
 Common Attributes
 -----------------
 
     for x in range(17):
         vlines.add(dwg.line(start=((2+x)*cm, 2*cm), end=((2+x)*cm, 21*cm)))
     shapes = dwg.add(dwg.g(id='shapes', fill='red'))
-    shapes.add(dwg.rect(insert=(5*cm, 5*cm), size=(45*mm, 45*mm)))
-    shapes.add(dwg.circle(center=(15*cm, 8*cm), r='2.5cm', fill='blue'))
-    shapes.add(dwg.ellipse(center=(10*cm, 15*cm), r=('5cm', '10mm')))
+
+    # set presentation attributes at object creation as SVG-Attributes
+    shapes.add(dwg.circle(center=(15*cm, 8*cm), r='2.5cm', stroke='blue', stroke_width=3))
+
+    # override the 'fill' attribute of the parent group 'shapes'
+    shapes.add(dwg.rect(insert=(5*cm, 5*cm), size=(45*mm, 45*mm), fill='blue', stroke='red', stroke_width=3))
+
+    # or set presentation attributes by helper functions of the Presentation-Mixin
+    ellipse = shapes.add(dwg.ellipse(center=(10*cm, 15*cm), r=('5cm', '10mm')))
+    ellipse.fill('green', opacity=0.5).stroke('black', width=5).dasharray([20, 20])
     dwg.save()
 
 def use_drawing(name):

File svgwrite/container.py

 
 from base import BaseElement
 from interface import IViewBox, ITransform, IXLink
+from mixins import Presentation
 
-class Group(BaseElement, ITransform):
+class Group(BaseElement, ITransform, Presentation):
     """ The <g> element is a container element for grouping together
     related graphics elements.
     """
     """
     elementname= 'defs'
 
-class Symbol(BaseElement, IViewBox):
+class Symbol(BaseElement, IViewBox, Presentation):
     """ The <symbol> element is used to define graphical template objects which
     can be instantiated by a <use> element. The use of <symbol> elements for
     graphics that are used multiple times in the same document adds structure and
         self.defs = Defs(factory=self) # defs container
         self.add(self.defs) # add defs as first element
 
-class Use(BaseElement, ITransform, IXLink):
+class Use(BaseElement, ITransform, IXLink, Presentation):
     """ The <use> element references another element and indicates that the graphical
     contents of that element is included/drawn at that given point in the document.
 
         self.update_id() # if href is an object - 'id' - attribute may be changed!
         return super(Use, self).get_xml()
 
-class Hyperlink(BaseElement, ITransform):
+class Hyperlink(BaseElement, ITransform, Presentation):
     """ The <a> element indicate links (also known as Hyperlinks or Web links).
 
     The remote resource (the destination for the link) is defined by a <IRI>

File svgwrite/data/full11.py

     types=empty_list,
     const=frozenset([u'bevel', u'miter', u'round', u'inherit'])),
 'stroke-miterlimit': SVGAttribute('stroke-miterlimit', anim=True,
-    types=frozenset([u'miterlimit']),
+    types=frozenset([u'number']),
     const=frozenset([u'inherit'])),
 'stroke-opacity': SVGAttribute('stroke-opacity', anim=True,
     types=frozenset([u'number']),

File svgwrite/data/tiny12.py

     const=frozenset([u'disable', u'magnify'])),
 }
 
-attribute_names = [u'slope', u'keySplines', u'rx', u'accumulate', u'bandwidth', u'attributeType', u'unicode', u'nav-right', u'arabic-form', u'y2', u'horiz-origin-x', u'underline-position', u'zoomAndPan', u'cap-height', u'defaultAction', u'to', u'syncBehavior', u'alphabetic', u'g2', u'g1', u'panose-1', u'strikethrough-thickness', u'attributeName', u'bbox', u'nav-up-left', u'nav-left', u'restart', u'target', u'xlink:actuate', u'rotate', u'resource', u'd', u'syncToleranceDefault', u'initialVisibility', u'transformBehavior', u'nav-up-right', u'keyTimes', u'x', u'requiredFormats', u'nav-next', u'glyph-name', u'xml:lang', u'mathematical', u'observer', u'repeatDur', u'hanging', u'y1', u'xml:base', u'ascent', u'event', u'strikethrough-position', u'overlay', u'rev', u'ry', u'overline-thickness', u'content', u'version', u'rel', u'focusable', u'requiredFonts', u'nav-down-right', u'xml:id', u'offset', u'additive', u'underline-thickness', u'font-family', u'by', u'mediaTime', u'timelineBegin', u'about', u'horiz-adv-x', u'widths', u'k', u'requiredFeatures', u'preserveAspectRatio', u'contentScriptType', u'origin', u'xml:space', u'xlink:href', u'height', u'baseProfile', u'cy', u'cx', u'path', u'xlink:role', u'from', u'u1', u'transform', u'units-per-em', u'u2', u'width', u'handler', u'font-variant', u'x-height', u'dur', u'xlink:arcrole', u'type', u'focusHighlight', u'mediaCharacterEncoding', u'xlink:title', u'editable', u'stemv', u'systemLanguage', u'x2', u'x1', u'ideographic', u'xlink:show', u'overline-position', u'syncTolerance', u'gradientUnits', u'r', u'values', u'typeof', u'mediaContentEncodings', u'property', u'requiredExtensions', u'repeatCount', u'ev:event', u'nav-down', u'mediaSize', u'pathLength', u'syncMaster', u'font-style', u'fill', u'end', u'descent', u'calcMode', u'min', u'stemh', u'id', u'unicode-range', u'nav-up', u'font-stretch', u'role', u'font-weight', u'begin', u'xlink:type', u'syncBehaviorDefault', u'max', u'snapshotTime', u'playbackOrder', u'keyPoints', u'nav-prev', u'propagate', u'phase', u'externalResourcesRequired', u'nav-down-left', u'class', u'lang', u'datatype', u'viewBox', u'points', u'accent-height', u'y']
-property_names = [u'stroke-linejoin', u'font-size', u'text-rendering', u'color-rendering', u'fill-opacity', u'color', u'shape-rendering', u'solid-color', u'stroke', u'stroke-linecap', u'vector-effect', u'stroke-width', u'font-style', u'fill', u'solid-opacity', u'fill-rule', u'viewport-fill-opacity', u'display-align', u'buffered-rendering', u'stroke-miterlimit', u'font-variant', u'stop-opacity', u'font-weight', u'opacity', u'direction', u'audio-level', u'visibility', u'unicode-bidi', u'line-increment', u'image-rendering', u'font-family', u'viewport-fill', u'text-align', u'stroke-opacity', u'stroke-dashoffset', u'text-anchor', u'stop-color', u'pointer-events', u'stroke-dasharray', u'display']
-media_group_names = ['audio-level', 'buffered-rendering', 'display', 'image-rendering', 'pointer-events', 'shape-rendering', 'text-rendering', 'viewport-fill', 'viewport-fill-opacity', 'visibility']
+attribute_names = [u'slope', u'keySplines', u'rx', u'accumulate', u'bandwidth',
+                   u'attributeType', u'unicode', u'nav-right', u'arabic-form',
+                   u'y2', u'horiz-origin-x', u'underline-position', u'zoomAndPan',
+                   u'cap-height', u'defaultAction', u'to', u'syncBehavior',
+                   u'alphabetic', u'g2', u'g1', u'panose-1', u'strikethrough-thickness',
+                   u'attributeName', u'bbox', u'nav-up-left', u'nav-left',
+                   u'restart', u'target', u'xlink:actuate', u'rotate', u'resource',
+                   u'd', u'syncToleranceDefault', u'initialVisibility',
+                   u'transformBehavior', u'nav-up-right', u'keyTimes',
+                   u'x', u'requiredFormats', u'nav-next', u'glyph-name',
+                   u'xml:lang', u'mathematical', u'observer', u'repeatDur',
+                   u'hanging', u'y1', u'xml:base', u'ascent', u'event',
+                   u'strikethrough-position', u'overlay', u'rev', u'ry',
+                   u'overline-thickness', u'content', u'version', u'rel',
+                   u'focusable', u'requiredFonts', u'nav-down-right', u'xml:id',
+                   u'offset', u'additive', u'underline-thickness', u'font-family',
+                   u'by', u'mediaTime', u'timelineBegin', u'about', u'horiz-adv-x',
+                   u'widths', u'k', u'requiredFeatures', u'preserveAspectRatio',
+                   u'contentScriptType', u'origin', u'xml:space', u'xlink:href',
+                   u'height', u'baseProfile', u'cy', u'cx', u'path', u'xlink:role',
+                   u'from', u'u1', u'transform', u'units-per-em', u'u2', u'width',
+                   u'handler', u'font-variant', u'x-height', u'dur', u'xlink:arcrole',
+                   u'type', u'focusHighlight', u'mediaCharacterEncoding',
+                   u'xlink:title', u'editable', u'stemv', u'systemLanguage',
+                   u'x2', u'x1', u'ideographic', u'xlink:show', u'overline-position',
+                   u'syncTolerance', u'gradientUnits', u'r', u'values', u'typeof',
+                   u'mediaContentEncodings', u'property', u'requiredExtensions',
+                   u'repeatCount', u'ev:event', u'nav-down', u'mediaSize', u'pathLength',
+                   u'syncMaster', u'font-style', u'fill', u'end', u'descent',
+                   u'calcMode', u'min', u'stemh', u'id', u'unicode-range',
+                   u'nav-up', u'font-stretch', u'role', u'font-weight', u'begin',
+                   u'xlink:type', u'syncBehaviorDefault', u'max', u'snapshotTime',
+                   u'playbackOrder', u'keyPoints', u'nav-prev', u'propagate',
+                   u'phase', u'externalResourcesRequired', u'nav-down-left',
+                   u'class', u'lang', u'datatype', u'viewBox', u'points',
+                   u'accent-height', u'y']
+property_names = [u'stroke-linejoin', u'font-size', u'text-rendering', u'color-rendering',
+                  u'fill-opacity', u'color', u'shape-rendering', u'solid-color', u'stroke',
+                  u'stroke-linecap', u'vector-effect', u'stroke-width', u'font-style',
+                  u'fill', u'solid-opacity', u'fill-rule', u'viewport-fill-opacity',
+                  u'display-align', u'buffered-rendering', u'stroke-miterlimit',
+                  u'font-variant', u'stop-opacity', u'font-weight', u'opacity', u'direction',
+                  u'audio-level', u'visibility', u'unicode-bidi', u'line-increment',
+                  u'image-rendering', u'font-family', u'viewport-fill', u'text-align',
+                  u'stroke-opacity', u'stroke-dashoffset', u'text-anchor', u'stop-color',
+                  u'pointer-events', u'stroke-dasharray', u'display']
+media_group_names = ['audio-level', 'buffered-rendering', 'display', 'image-rendering',
+                     'pointer-events', 'shape-rendering', 'text-rendering',
+                     'viewport-fill', 'viewport-fill-opacity', 'visibility']
 
 elements = {
     'a': SVGElement('a',

File svgwrite/metadata.py

 # Copyright (C) 2010, Manfred Moitzi
 # License: GPLv3
 
-VERSION = '0.1.1'
+VERSION = '0.2'
 AUTHOR_NAME = 'Manfred Moitzi'
 AUTHOR_EMAIL = 'mozman@gmx.at'
 CYEAR = '2010'

File svgwrite/mixins.py

 # Copyright (C) 2010, Manfred Moitzi
 # License: GPLv3
 
+from utils import strlist
+
 class Presentation(object):
     """
     Helper methods to set presentation attributes.
             self['fill-rule'] = rule
         if opacity:
             self['fill-opacity'] = opacity
+        return self
 
     def stroke(self, color=None, width=None, opacity=None, linecap=None,
                linejoin=None, miterlimit=None):
             self['stroke-linejoin'] = linejoin
         if miterlimit:
             self['stroke-miterlimit'] = miterlimit
+        return self
 
-    def dasharray(self, definition=None, offset=None):
+    def dasharray(self, dasharray=None, offset=None):
         """
-        Set SVG Properties **stroke-dashoffset** and **stroke-array**.
+        Set SVG Properties **stroke-dashoffset** and **stroke-dasharray**.
 
+        Where *dasharray* specify the lengths of alternating dashes and gaps as
+        <list> of <int> or <float> values or a <string> of comma and/or white
+        space separated <lengths> or <percentages>. (e.g. as <list> dasharray=[1, 0.5]
+        or as <string> dasharray='1 0.5')
         """
-        if definition:
-            self['stroke-array'] = definition
+        if dasharray:
+            self['stroke-dasharray'] = strlist(dasharray, ' ')
         if offset:
             self['stroke-dashoffset'] = offset
+        return self
+
+class MediaGroup(object):
+    """
+    Helper methods to set media group attributes.
+
+    """
 
     def viewport_fill(self, color=None, opacity=None):
         """
             self['viewport-fill'] = color
         if opacity:
             self['viewport-fill-opacity'] = opacity
+        return self

File svgwrite/path.py

 from base import BaseElement
 from utils import strlist
 from interface import ITransform
+from mixins import Presentation
 
-class Path(BaseElement, ITransform):
+class Path(BaseElement, ITransform, Presentation):
     """ The <path> element represent the outline of a shape which can be filled,
     stroked, used as a clipping path, or any combination of the three.
 

File svgwrite/shapes.py

 
 from base import BaseElement
 from interface import ITransform
+from mixins import Presentation
 
-class Line(BaseElement, ITransform):
+class Line(BaseElement, ITransform, Presentation):
     """ The <line> element defines a line segment that starts at one point and ends
     at another.
 
         self['x2'] = x2
         self['y2'] = y2
 
-class Rect(BaseElement, ITransform):
+class Rect(BaseElement, ITransform, Presentation):
     """ The <rect> element defines a rectangle which is axis-aligned with the current
     user coordinate system. Rounded rectangles can be achieved by setting appropriate
     values for attributes <rx> and <ry>.
         if rx: self['rx'] = rx
         if ry: self['ry'] = ry
 
-class Circle(BaseElement, ITransform):
+class Circle(BaseElement, ITransform, Presentation):
     """ The <circle> element defines a circle based on a center point and a radius.
 
     .. automethod:: svgwrite.shapes.Circle.__init__
         self['cy'] = cy
         self['r'] = r
 
-class Ellipse(BaseElement, ITransform):
+class Ellipse(BaseElement, ITransform, Presentation):
     """ The <ellipse> element defines an ellipse which is axis-aligned with the
     current user coordinate system based on a center point and two radii.
 
         self['rx'] = rx
         self['ry'] = ry
 
-class Polyline(BaseElement, ITransform):
+class Polyline(BaseElement, ITransform, Presentation):
     """ The <polyline> element defines a set of connected straight line segments.
     Typically, <polyline> elements define open shapes.
 

File svgwrite/text.py

 
 from base import BaseElement
 from interface import ITransform, IXLink
+from mixins import Presentation
 from utils import iterflatlist, strlist
 
-class TSpan(BaseElement):
+class TSpan(BaseElement, Presentation):
     """
     Within a :class:`~svgwrite.Text` element, text and font properties
     and the current text position can be adjusted with absolute or relative
     """
     elementname = 'text'
 
-class TRef(BaseElement, IXLink):
+class TRef(BaseElement, IXLink, Presentation):
     """
     The textual content for a <text> can be either character data directly
     embedded within the <text> element or the character data content of a
         self.update_id() # if href is an object - 'id' - attribute may be changed!
         return super(TRef, self).get_xml()
 
-class TextPath(BaseElement, IXLink):
+class TextPath(BaseElement, IXLink, Presentation):
     """
     In addition to text drawn in a straight line, SVG also includes the
     ability to place text along the shape of a <path> element. To specify that
     def add(self, element):
         raise NotImplementedError("add() not supported by TBreak class.")
 
-class TextArea(BaseElement, ITransform):
+class TextArea(BaseElement, ITransform, Presentation):
     """
     At this time <textArea> is only available for SVG 1.2 Tiny profile.
 

File svgwrite/utils.py

 
     """
     def percent(value):
-        value = float(value)
-        if value < 0.:
-            value = 0.
-        if value > 100.:
-            value = 100.
+        value = int(value)
+        if value < 0:
+            value = 0
+        if value > 100:
+            value = 100
         return value
 
     if mode.upper() == 'RGB':
         return u"rgb(%d,%d,%d)" % (int(r) & 255, int(g) & 255, int(b) & 255)
     elif mode == "%":
-        return u"rgb(%.3f%%,%.3f%%,%.3f%%)" % (percent(r), percent(g), percent(b))
+        # see http://www.w3.org/TR/SVG11/types.html#DataTypeColor
+        # percentage is an 'integer' value
+        return u"rgb(%d%%,%d%%,%d%%)" % (percent(r), percent(g), percent(b))
     else:
         raise ValueError("Invalid mode '%s'" % mode)
 
     :returns: <string>
 
     """
-    return seperator.join([str(value) for value in iterflatlist(values) if value is not None])
+    if isinstance(values, basestring):
+        return values
+    else:
+        return seperator.join([str(value) for value in iterflatlist(values) if value is not None])
 
 def get_unit(coordinate):
     """

File tests/test_mediagroup.py

+#!/usr/bin/env python
+#coding:utf-8
+# Author:  mozman --<mozman@gmx.at>
+# Purpose: test MediaGroup mixin
+# Created: 24.10.2010
+# Copyright (C) 2010, Manfred Moitzi
+# License: GPLv3
+
+import unittest
+
+from svgwrite.base import BaseElement
+from svgwrite.mixins import MediaGroup
+
+class MediaGroupClass(BaseElement, MediaGroup):
+    elementname = "image" # element with valid media group attributes
+
+class TestMediaGroupMixin(unittest.TestCase):
+    def test_viewport_fill(self):
+        obj = MediaGroupClass(debug=True, profile='tiny')
+        obj.viewport_fill(color='red', opacity=1.0)
+        self.assertEqual(obj.tostring(),
+                         '<image viewport-fill="red" viewport-fill-opacity="1.0" />')
+
+if __name__=='__main__':
+    unittest.main()

File tests/test_presentation.py

+#!/usr/bin/env python
+#coding:utf-8
+# Author:  mozman --<mozman@gmx.at>
+# Purpose: test presentation mixin
+# Created: 24.10.2010
+# Copyright (C) 2010, Manfred Moitzi
+# License: GPLv3
+
+import unittest
+
+from svgwrite.base import BaseElement
+from svgwrite.mixins import Presentation
+from svgwrite import rgb
+
+class PresentationClass(BaseElement, Presentation):
+    elementname = "line" # element with valid presentation attributes
+
+class TestPresentationMixin(unittest.TestCase):
+    def test_fill(self):
+        obj = PresentationClass(debug=True, profile='full')
+        obj.fill(color='red', rule="evenodd", opacity=1.0)
+        self.assertEqual(obj.tostring(),
+                         '<line fill="red" fill-opacity="1.0" fill-rule="evenodd" />')
+
+    def test_fill_rgb_values(self):
+        obj = PresentationClass(debug=True, profile='full')
+        obj.fill(color=rgb(10, 20, 30), rule="evenodd", opacity=1.0)
+        self.assertEqual(obj.tostring(),
+                         '<line fill="rgb(10,20,30)" fill-opacity="1.0" fill-rule="evenodd" />')
+
+    def test_fill_rgb_percentage(self):
+        obj = PresentationClass(debug=True, profile='full')
+        obj.fill(color=rgb(10, 20, 30, '%'), rule="evenodd", opacity=1.0)
+        self.assertEqual(obj.tostring(),
+                         '<line fill="rgb(10%,20%,30%)" fill-opacity="1.0" fill-rule="evenodd" />')
+
+    def test_stroke(self):
+        obj = PresentationClass(debug=True, profile='full')
+        obj.stroke(color='red', width=2, opacity=0.5, linecap='round',
+                   linejoin='round', miterlimit='1.5')
+        self.assertEqual(obj.tostring(),
+                         '<line stroke="red" ' \
+                         'stroke-linecap="round" ' \
+                         'stroke-linejoin="round" ' \
+                         'stroke-miterlimit="1.5" ' \
+                         'stroke-opacity="0.5" ' \
+                         'stroke-width="2" />')
+
+    def test_dasharray(self):
+        obj = PresentationClass(debug=True, profile='full')
+        obj.dasharray([1., 0.5], offset=0.5)
+        self.assertEqual(obj.tostring(),
+                         '<line stroke-dasharray="1.0 0.5" stroke-dashoffset="0.5" />')
+
+        obj.dasharray('1.0 0.5', offset=0.5)
+        self.assertEqual(obj.tostring(),
+                         '<line stroke-dasharray="1.0 0.5" stroke-dashoffset="0.5" />')
+
+    def test_combi_call(self):
+        obj = PresentationClass(debug=True, profile='full')
+        obj.fill('red').stroke('blue')
+        self.assertEqual(obj.tostring(),
+                         '<line fill="red" stroke="blue" />')
+
+if __name__=='__main__':
+    unittest.main()

File tests/test_utils.py

         self.assertEqual(rgb(257, 257, 257), "rgb(1,1,1)")
 
     def test_rgb_percent(self):
-        self.assertEqual(rgb(50, 50, 50, '%'), "rgb(50.000%,50.000%,50.000%)")
-        self.assertEqual(rgb(mode='%'), "rgb(0.000%,0.000%,0.000%)")
+        self.assertEqual(rgb(50, 50, 50, '%'), "rgb(50%,50%,50%)")
+        self.assertEqual(rgb(mode='%'), "rgb(0%,0%,0%)")
         # value overflow
-        self.assertEqual(rgb(101, -1, 101, '%'), "rgb(100.000%,0.000%,100.000%)")
+        self.assertEqual(rgb(101, -1, 101, '%'), "rgb(100%,0%,100%)")
 
     def test_rgb_invalid_mode(self):
         self.assertRaises(ValueError, rgb, mode='$')
         self.assertEqual(strlist( [(5, 'abc', None), (1, 2, None)] ), "5,abc,1,2")
         self.assertEqual(strlist( [(1,None,3), 4]), "1,3,4")
 
+    def test_string(self):
+        self.assertEqual(strlist("5,abc,1,2") , "5,abc,1,2")
+
 class TestRectTopLeftCorner(unittest.TestCase):
     def test_top_left(self):
         res = rect_top_left_corner(insert=(10,10), size=(10,10))