Revision: 6322
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6322&view=rev
Author:   mdboom
Date:     2008-10-24 17:12:24 +0000 (Fri, 24 Oct 2008)

Log Message:
-----------
Add mathtext API docs.

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/mathtext.py

Added Paths:
-----------
    trunk/matplotlib/doc/api/mathtext_api.rst

Added: trunk/matplotlib/doc/api/mathtext_api.rst
===================================================================
--- trunk/matplotlib/doc/api/mathtext_api.rst                           (rev 0)
+++ trunk/matplotlib/doc/api/mathtext_api.rst   2008-10-24 17:12:24 UTC (rev 
6322)
@@ -0,0 +1,14 @@
+*******************
+matplotlib mathtext
+*******************
+
+.. inheritance-diagram:: matplotlib.mathtext
+   :parts: 1
+
+:mod:`matplotlib.mathtext`
+=============================
+
+.. automodule:: matplotlib.mathtext
+   :members:
+   :undoc-members:
+   :show-inheritance:

Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2008-10-24 15:53:59 UTC (rev 
6321)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2008-10-24 17:12:24 UTC (rev 
6322)
@@ -1,175 +1,21 @@
 r"""
+:mod:`~matplotlib.mathtext` is a module for parsing a subset of the
+TeX math syntax and drawing them to a matplotlib backend.
 
-OVERVIEW
+For a tutorial of its usage see :ref:`mathtext-tutorial`.  This
+document is primarily concerned with implementation details.
 
-  mathtext is a module for parsing TeX expressions and drawing them
-  into a matplotlib.ft2font image buffer.  You can draw from this
-  buffer into your backend.
+The module uses pyparsing_ to parse the TeX expression.
 
-  A large set of the TeX symbols are provided (see below).
-  Subscripting and superscripting are supported, as well as the
-  over/under style of subscripting with \sum, \int, etc.
+.. _pyparsing: http://pyparsing.wikispaces.com/
 
-  The module uses pyparsing to parse the TeX expression, an so can
-  handle fairly complex TeX expressions Eg, the following renders
-  correctly
+The Bakoma distribution of the TeX Computer Modern fonts, and STIX
+fonts are supported.  There is experimental support for using
+arbitrary fonts, but results may vary without proper tweaking and
+metrics for those fonts.
 
-  s = r'$\mathcal{R}\prod_{i=\alpha\mathcal{B}}^\infty a_i\sin(2 \pi f x_i)$'
-
-  Different fonts may be selected:
-    \mathcal      Calligraphic fonts
-    \mathrm       Roman (upright) font
-    \mathit       Italic font
-    \mathtt       Typewriter (monospaced) font, similar to Courier
-
-  Additionally, if using the STIX fonts:
-    \mathbb       Blackboard (double-struck) font
-    \mathcircled  Circled characters
-    \mathfrak     Fraktur (Gothic-style) font
-    \mathscr      Script (cursive) font
-    \mathsf       Sans-serif font
-
-  The following accents are provided: \hat, \breve, \grave, \bar,
-  \acute, \tilde, \vec, \dot, \ddot.  All of them have the same
-  syntax, eg to make an overbar you do \bar{o} or to make an o umlaut
-  you do \ddot{o}.  The shortcuts are also provided, eg: \"o \'e \`e
-  \~n \.x \^y
-
-  The spacing elements \ , \/ and \hspace{num} are provided.  \/
-  inserts a small space, and \hspace{num} inserts a fraction of the
-  current fontsize.  Eg, if num=0.5 and the fontsize is 12.0,
-  hspace{0.5} inserts 6 points of space
-
-
-
-  If you find TeX expressions that don't parse or render properly,
-  please email me, but please check KNOWN ISSUES below first.
-
-REQUIREMENTS
-
-  mathtext requires matplotlib.ft2font.  Set BUILD_FT2FONT=True in
-  setup.py.  See BACKENDS below for a summary of availability by
-  backend.
-
-LICENSING:
-
-  The computer modern fonts this package uses are part of the BaKoMa
-  fonts, which are (now) free for commercial and noncommercial use and
-  redistribution; see license/LICENSE_BAKOMA in the matplotlib src
-  distribution for redistribution requirements.
-
-USAGE:
-
-  See http://matplotlib.sf.net/users/mathtext.html for a tutorial
-  introduction.
-
-  Any text element (xlabel, ylabel, title, text, etc) can use TeX
-  markup, as in
-
-    xlabel(r'$\Delta_i$')
-           ^
-        use raw strings
-
-  Math and non-math can be interpresed in the same string.  E.g.,
-
-    r'My label $x_i$'.
-
-  A large set of the TeX symbols are provided.  Subscripting and
-  superscripting are supported, as well as the over/under style of
-  subscripting with \sum, \int, etc.
-
-
-  Allowed TeX symbols:
-
-  $ \% \AA \AE \BbbC \BbbN \BbbP \BbbQ \BbbR \BbbZ \Bumpeq \Cap \Colon
-  \Cup \Delta \Doteq \Downarrow \Equiv \Finv \Gamma \H \Im \L \Lambda
-  \Ldsh \Leftarrow \Leftrightarrow \Lleftarrow \Lsh \Nearrow \Nwarrow
-  \O \OE \Omega \P \Phi \Pi \Psi \Rdsh \Re \Rightarrow \Rrightarrow
-  \Rsh \S \Searrow \Sigma \Subset \Supset \Swarrow \Theta \Uparrow
-  \Updownarrow \Upsilon \Vdash \Vert \Vvdash \Xi \_ \__sqrt__ \ac
-  \acute \acwopencirclearrow \adots \ae \aleph \alpha \angle \approx
-  \approxeq \approxident \arceq \ast \asymp \backcong \backprime
-  \backsim \backsimeq \backslash \bar \barleftarrow \barwedge \because
-  \beta \beth \between \bigcap \bigcirc \bigcup \bigodot \bigoplus
-  \bigotimes \bigstar \bigtriangledown \bigtriangleup \biguplus
-  \bigvee \bigwedge \blacksquare \blacktriangle \blacktriangledown
-  \blacktriangleleft \blacktriangleright \bot \bowtie \boxbar \boxdot
-  \boxminus \boxplus \boxtimes \breve \bullet \bumpeq \c \candra \cap
-  \carriagereturn \cdot \cdotp \cdots \check \checkmark \chi \circ
-  \circeq \circledR \circledS \circledast \circledcirc \circleddash
-  \circumflexaccent \clubsuit \clubsuitopen \colon \coloneq
-  \combiningacuteaccent \combiningbreve \combiningdiaeresis
-  \combiningdotabove \combininggraveaccent \combiningoverline
-  \combiningrightarrowabove \combiningtilde \complement \cong \coprod
-  \copyright \cup \cupdot \curlyeqprec \curlyeqsucc \curlyvee
-  \curlywedge \curvearrowleft \curvearrowright \cwopencirclearrow \d
-  \dag \daleth \danger \dashv \ddag \ddddot \dddot \ddot \ddots
-  \degree \delta \diamond \diamondsuit \digamma \div \divideontimes
-  \dot \doteq \dotminus \dotplus \dots \doublebarwedge ? \downarrow
-  \downdownarrows \downharpoonleft \downharpoonright \downzigzagarrow
-  \ell \emdash \emptyset \endash \enspace \epsilon \eqcirc \eqcolon
-  \eqdef \eqgtr \eqless \eqsim \equiv \eta \eth \exists \fallingdotseq
-  \flat \forall \frakC \frakZ \frown \gamma \geq \geqq \gg \ggg \gimel
-  \gneqq \gnsim \grave \greater \gtrdot \gtreqless \gtrless \gtrsim
-  \hat \heartsuit \hookleftarrow \hookrightarrow \i \iiint \iint
-  \imageof \imath \in \infty \int \intercal \invnot \iota \jmath \k
-  \kappa \kernelcontraction \l \lambda \lambdabar \lasp \lbrace
-  \lbrack \lceil \leftangle \leftarrow \leftarrowtail \leftbrace
-  \leftharpoonaccent \leftharpoondown \leftharpoonup \leftleftarrows
-  \leftparen \leftrightarrow \leftrightarrows \leftrightharpoons
-  \leftthreetimes \leq \leqq \less \lessdot \lesseqgtr \lessgtr
-  \lesssim \lfloor \ll \llcorner \lll \lneqq \lnsim \looparrowleft
-  \looparrowright \lq \lrcorner \ltimes \maltese \mapsdown \mapsfrom
-  \mapsto \mapsup \measeq \measuredangle \mho \mid \minus \models \mp
-  \mu \multimap \nLeftarrow \nLeftrightarrow \nRightarrow \nVDash
-  \nVdash \nabla \napprox \natural \ncong \ne \nearrow \neg \nequiv
-  \nexists \ngeq \ngtr \ni \nleftarrow \nleftrightarrow \nleq \nless
-  \nmid \not \notin \nparallel \nprec \nrightarrow \nsim \nsime
-  \nsubset \nsubseteq \nsucc \nsupset \nsupseteq \ntriangleleft
-  \ntrianglelefteq \ntriangleright \ntrianglerighteq \nu \nvDash
-  \nvdash \nwarrow \o \obar \ocirc \odot \oe \oiiint \oiint \oint
-  \omega \ominus \oplus \origof \oslash \otimes \overarc
-  \overleftarrow \overleftrightarrow \parallel \partial \phi \pi
-  \pitchfork \pm \prec \preccurlyeq \preceq \precnsim \precsim \prime
-  \prod \propto \prurel \psi \quad \questeq \rasp \rbrace \rbrack
-  \rceil \rfloor \rho \rightangle \rightarrow \rightarrowbar
-  \rightarrowtail \rightbrace \rightharpoonaccent \rightharpoondown
-  \rightharpoonup \rightleftarrows \rightleftharpoons \rightparen
-  \rightrightarrows \rightthreetimes \rightzigzagarrow \risingdotseq
-  \rq \rtimes \scrB \scrE \scrF \scrH \scrI \scrL \scrM \scrR \scre
-  \scrg \scro \scurel \searrow \sharp \sigma \sim \simeq \slash
-  \smallsetminus \smile \solbar \spadesuit \spadesuitopen
-  \sphericalangle \sqcap \sqcup \sqsubset \sqsubseteq \sqsupset
-  \sqsupseteq \ss \star \stareq \sterling \subset \subseteq \subsetneq
-  \succ \succcurlyeq \succeq \succnsim \succsim \sum \supset \supseteq
-  \supsetneq \swarrow \t \tau \textasciiacute \textasciicircum
-  \textasciigrave \textasciitilde \textexclamdown \textquestiondown
-  \textquotedblleft \textquotedblright \therefore \theta \thickspace
-  \thinspace \tilde \times \to \top \triangledown \triangleleft
-  \trianglelefteq \triangleq \triangleright \trianglerighteq
-  \turnednot \twoheaddownarrow \twoheadleftarrow \twoheadrightarrow
-  \twoheaduparrow \ulcorner \underbar \uparrow \updownarrow
-  \updownarrowbar \updownarrows \upharpoonleft \upharpoonright \uplus
-  \upsilon \upuparrows \urcorner \vDash \varepsilon \varkappa
-  \varnothing \varphi \varpi \varrho \varsigma \vartheta \vartriangle
-  \vartriangleleft \vartriangleright \vdash \vdots \vec \vee \veebar
-  \veeeq \vert \wedge \wedgeq \widehat \widetilde \wp \wr \xi \yen
-  \zeta \{ \| \}
-
-BACKENDS
-
-  mathtext currently works with all backends.
-
-KNOWN ISSUES:
-
-  - Certainly there are some...
-
-Author    : John Hunter <[EMAIL PROTECTED]>
-            Michael Droettboom <[EMAIL PROTECTED]>
-               (rewrite based on TeX box layout algorithms)
-Copyright : John Hunter (2004,2005)
-License   : matplotlib license (PSF compatible)
-
+If you find TeX expressions that don't parse or render properly,
+please email [EMAIL PROTECTED], but please check KNOWN ISSUES below first.
 """
 from __future__ import division
 import os
@@ -214,10 +60,9 @@
 def get_unicode_index(symbol):
     """get_unicode_index(symbol) -> integer
 
-Return the integer index (from the Unicode table) of symbol.
-symbol can be a single unicode character, a TeX command (i.e. r'\pi'),
-or a Type1 symbol name (i.e. 'phi').
-
+Return the integer index (from the Unicode table) of symbol.  *symbol*
+can be a single unicode character, a TeX command (i.e. r'\pi'), or a
+Type1 symbol name (i.e. 'phi').
 """
     # From UTF #25: U+2212 minus sign is the preferred
     # representation of the unary and binary minus sign rather than
@@ -239,32 +84,62 @@
 
 
 class MathtextBackend(object):
+    """
+    The base class for the mathtext backend-specific code.  The
+    purpose of :class:`MathtextBackend` subclasses is to interface
+    between mathtext and a specific matplotlib graphics backend.
+
+    Subclasses need to override the following:
+
+      - :meth:`render_glyph`
+      - :meth:`render_filled_rect`
+      - :meth:`get_results`
+
+    And optionally, if you need to use a Freetype hinting style:
+
+      - :meth:`get_hinting_type`
+    """
     def __init__(self):
         self.fonts_object = None
 
     def set_canvas_size(self, w, h, d):
-        'Dimension the drawing canvas; may be a noop'
+        'Dimension the drawing canvas'
         self.width  = w
         self.height = h
         self.depth  = d
 
     def render_glyph(self, ox, oy, info):
+        """
+        Draw a glyph described by *info* to the reference point (*ox*,
+        *oy*).
+        """
         raise NotImplementedError()
 
     def render_filled_rect(self, x1, y1, x2, y2):
+        """
+        Draw a filled black rectangle from (*x1*, *y1*) to (*x2*, *y2*).
+        """
         raise NotImplementedError()
 
     def get_results(self, box):
-        """Return a backend specific tuple of things to return to the
-        backend after all processing is done."""
+        """
+        Return a backend-specific tuple to return to the backend after
+        all processing is done.
+        """
         raise NotImplementedError()
 
     def get_hinting_type(self):
+        """
+        Get the Freetype hinting type to use with this particular
+        backend.
+        """
         return LOAD_NO_HINTING
 
 class MathtextBackendBbox(MathtextBackend):
-    """A backend whose only purpose is to get a precise bounding box.
-    Only required for the Agg backend."""
+    """
+    A backend whose only purpose is to get a precise bounding box.
+    Only required for the Agg backend.
+    """
 
     def __init__(self, real_backend):
         MathtextBackend.__init__(self)
@@ -310,6 +185,10 @@
         self.real_backend.oy = self.bbox[1]
 
 class MathtextBackendAggRender(MathtextBackend):
+    """
+    Render glyphs and rectangles to an FTImage buffer, which is later
+    transferred to the Agg image by the Agg backend.
+    """
     def __init__(self):
         self.ox = 0
         self.oy = 0
@@ -353,9 +232,17 @@
         return self.image, self.depth
 
 def MathtextBackendBitmap():
+    """
+    A backend to generate standalone mathtext images.  No additional
+    matplotlib backend is required.
+    """
     return MathtextBackendBbox(MathtextBackendBitmapRender())
 
 class MathtextBackendPs(MathtextBackend):
+    """
+    Store information to write a mathtext rendering to the PostScript
+    backend.
+    """
     def __init__(self):
         self.pswriter = StringIO()
         self.lastfont = None
@@ -393,6 +280,10 @@
                 self.fonts_object.get_used_characters())
 
 class MathtextBackendPdf(MathtextBackend):
+    """
+    Store information to write a mathtext rendering to the PDF
+    backend.
+    """
     def __init__(self):
         self.glyphs = []
         self.rects = []
@@ -417,6 +308,10 @@
                 self.fonts_object.get_used_characters())
 
 class MathtextBackendSvg(MathtextBackend):
+    """
+    Store information to write a mathtext rendering to the SVG
+    backend.
+    """
     def __init__(self):
         self.svg_glyphs = []
         self.svg_rects = []
@@ -442,6 +337,11 @@
                 self.fonts_object.get_used_characters())
 
 class MathtextBackendCairo(MathtextBackend):
+    """
+    Store information to write a mathtext rendering to the Cairo
+    backend.
+    """
+
     def __init__(self):
         self.glyphs = []
         self.rects = []
@@ -466,7 +366,7 @@
 
 class Fonts(object):
     """
-    An abstract base class for fonts that want to render mathtext
+    An abstract base class for a system of fonts to use for mathtext.
 
     The class must be able to take symbol keys and font file names and
     return the character metrics.  It also delegates to a backend class
@@ -474,11 +374,15 @@
     """
 
     def __init__(self, default_font_prop, mathtext_backend):
-        """default_font_prop: A FontProperties object to use for the
-        default non-math font, or the base font for Unicode font
-        rendering.
-        mathtext_backend: A subclass of MathTextBackend used to
-        delegate the actual rendering."""
+        """
+        *default_font_prop*: A
+        :class:`~matplotlib.font_manager.FontProperties` object to use
+        for the default non-math font, or the base font for Unicode
+        (generic) font rendering.
+
+        *mathtext_backend*: A subclass of :class:`MathTextBackend`
+        used to delegate the actual rendering.
+        """
         self.default_font_prop = default_font_prop
         self.mathtext_backend = mathtext_backend
         # Make these classes doubly-linked
@@ -486,51 +390,86 @@
         self.used_characters = {}
 
     def destroy(self):
-        """Fix any cyclical references before the object is about
-        to be destroyed."""
+        """
+        Fix any cyclical references before the object is about
+        to be destroyed.
+        """
         self.used_characters = None
 
     def get_kern(self, font1, fontclass1, sym1, fontsize1,
                  font2, fontclass2, sym2, fontsize2, dpi):
         """
-        Get the kerning distance for font between sym1 and sym2.
+        Get the kerning distance for font between *sym1* and *sym2*.
 
-        fontX: one of the TeX font names, tt, it, rm, cal, sf, bf or
-               default (non-math)
-        symX:  a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
-        fontsizeX: the fontsize in points
-        dpi: the current dots-per-inch
+        *fontX*: one of the TeX font names::
 
-        sym is a single symbol(alphanum, punct) or a special symbol
-        like \sigma.
+          tt, it, rm, cal, sf, bf or default (non-math)
 
+        *fontclassX*: TODO
+
+        *symX*: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+
+        *fontsizeX*: the fontsize in points
+
+        *dpi*: the current dots-per-inch
         """
         return 0.
 
     def get_metrics(self, font, font_class, sym, fontsize, dpi):
         """
-        font: one of the TeX font names, tt, it, rm, cal, sf, bf or
-               default (non-math)
-        sym:  a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
-        fontsize: font size in points
-        dpi: current dots-per-inch
+        *font*: one of the TeX font names::
 
-          advance
-          height
-          width
-          xmin, xmax, ymin, ymax  - the ink rectangle of the glyph
-          iceberg - the distance from the baseline to the top of the glyph.
-             horiBearingY in Truetype parlance, height in TeX parlance
+          tt, it, rm, cal, sf, bf or default (non-math)
+
+        *font_class*: TODO
+
+        *sym*:  a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+
+        *fontsize*: font size in points
+
+        *dpi*: current dots-per-inch
+
+        Returns an object with the following attributes:
+
+          - *advance*: The advance distance (in points) of the glyph.
+
+          - *height*: The height of the glyph in points.
+
+          - *width*: The width of the glyph in points.
+
+          - *xmin*, *xmax*, *ymin*, *ymax* - the ink rectangle of the glyph
+
+          - *iceberg* - the distance from the baseline to the top of
+            the glyph.  This corresponds to TeX's definition of
+            "height".
         """
         info = self._get_info(font, font_class, sym, fontsize, dpi)
         return info.metrics
 
     def set_canvas_size(self, w, h, d):
-        'Dimension the drawing canvas; may be a noop'
+        """
+        Set the size of the buffer used to render the math expression.
+        Only really necessary for the bitmap backends.
+        """
         self.width, self.height, self.depth = ceil(w), ceil(h), ceil(d)
         self.mathtext_backend.set_canvas_size(self.width, self.height, 
self.depth)
 
     def render_glyph(self, ox, oy, facename, font_class, sym, fontsize, dpi):
+        """
+        Draw a glyph at
+
+          - *ox*, *oy*: position
+
+          - *facename*: One of the TeX face names
+
+          - *font_class*:
+
+          - *sym*: TeX symbol name or single character
+
+          - *fontsize*: fontsize in points
+
+          - *dpi*: The dpi to draw at.
+        """
         info = self._get_info(facename, font_class, sym, fontsize, dpi)
         realpath, stat_key = get_realpath_and_stat(info.font.fname)
         used_characters = self.used_characters.setdefault(
@@ -539,31 +478,52 @@
         self.mathtext_backend.render_glyph(ox, oy, info)
 
     def render_rect_filled(self, x1, y1, x2, y2):
+        """
+        Draw a filled rectangle from (*x1*, *y1*) to (*x2*, *y2*).
+        """
         self.mathtext_backend.render_rect_filled(x1, y1, x2, y2)
 
     def get_xheight(self, font, fontsize, dpi):
+        """
+        Get the xheight for the given *font* and *fontsize*.
+        """
         raise NotImplementedError()
 
     def get_underline_thickness(self, font, fontsize, dpi):
+        """
+        Get the line thickness that matches the given font.  Used as a
+        base unit for drawing lines such as in a fraction or radical.
+        """
         raise NotImplementedError()
 
     def get_used_characters(self):
+        """
+        Get the set of characters that were used in the math
+        expression.  Used by backends that need to subset fonts so
+        they know which glyphs to include.
+        """
         return self.used_characters
 
     def get_results(self, box):
+        """
+        Get the data needed by the backend to render the math
+        expression.  The return value is backend-specific.
+        """
         return self.mathtext_backend.get_results(box)
 
     def get_sized_alternatives_for_symbol(self, fontname, sym):
         """
         Override if your font provides multiple sizes of the same
-        symbol.
+        symbol.  Should return a list of symbols matching *sym* in
+        various sizes.  The expression renderer will select the most
+        appropriate size for a given situation from this list.
         """
         return [(fontname, sym)]
 
 class TruetypeFonts(Fonts):
     """
     A generic base class for all font setups that use Truetype fonts
-    (through ft2font)
+    (through FT2Font).
     """
     class CachedFont:
         def __init__(self, font):
@@ -589,8 +549,6 @@
         Fonts.destroy(self)
 
     def _get_font(self, font):
-        """Looks up a CachedFont with its charmap and inverse charmap.
-        font may be a TeX font name (cal, rm, it etc.), or postscript name."""
         if font in self.fontmap:
             basename = self.fontmap[font]
         else:
@@ -611,7 +569,6 @@
         return 0.
 
     def _get_info(self, fontname, font_class, sym, fontsize, dpi):
-        'load the cmfont, metrics and glyph with caching'
         key = fontname, font_class, sym, fontsize, dpi
         bunch = self.glyphd.get(key)
         if bunch is not None:
@@ -665,8 +622,9 @@
         return xHeight
 
     def get_underline_thickness(self, font, fontsize, dpi):
-        # This function used to grab underline thickness from the font,
-        # but that information is just too un-reliable, so it is now hardcoded.
+        # This function used to grab underline thickness from the font
+        # metrics, but that information is just too un-reliable, so it
+        # is now hardcoded.
         return ((0.75 / 12.0) * fontsize * dpi) / 72.0
 
     def get_kern(self, font1, fontclass1, sym1, fontsize1,
@@ -681,7 +639,10 @@
 
 class BakomaFonts(TruetypeFonts):
     """
-    Use the Bakoma true type fonts for rendering
+    Use the Bakoma TrueType fonts for rendering.
+
+    Symbols are strewn about a number of font files, each of which has
+    its own proprietary 8-bit encoding.
     """
     _fontmap = { 'cal' : 'cmsy10',
                  'rm'  : 'cmr10',
@@ -788,15 +749,19 @@
         _size_alternatives[alias] = _size_alternatives[target]
 
     def get_sized_alternatives_for_symbol(self, fontname, sym):
-        alternatives = self._size_alternatives.get(sym)
-        if alternatives:
-            return alternatives
-        return [(fontname, sym)]
+        return self._size_alternatives.get(sym, [(fontname, sym)])
 
 class UnicodeFonts(TruetypeFonts):
-    """An abstract base class for handling Unicode fonts.
     """
+    An abstract base class for handling Unicode fonts.
 
+    While some reasonably complete Unicode fonts (such as DejaVu) may
+    work in some situations, the only Unicode font I'm aware of with a
+    complete set of math symbols is STIX.
+
+    This class will "fallback" on the Bakoma fonts when a required
+    symbol can not be found in the font.
+    """
     fontmap = {}
     use_cmex = True
 
@@ -900,7 +865,15 @@
 
 class StixFonts(UnicodeFonts):
     """
-    A font handling class for the STIX fonts
+    A font handling class for the STIX fonts.
+
+    In addition to what UnicodeFonts provides, this class:
+
+    - supports "virtual fonts" which are complete alpha numeric
+      character sets with different font styles at special Unicode
+      code points, such as "Blackboard".
+
+    - handles sized alternative characters for the STIXSizeX fonts.
     """
     _fontmap = { 'rm'  : 'STIXGeneral',
                  'it'  : 'STIXGeneral:italic',
@@ -994,7 +967,7 @@
 
 class StixSansFonts(StixFonts):
     """
-    A font handling class for the STIX fonts (using sans-serif
+    A font handling class for the STIX fonts (that uses sans-serif
     characters by default).
     """
     _sans = True
@@ -1187,9 +1160,9 @@
     pass
 
 class Node(object):
-    """A node in the TeX box model
-    node133
     """
+    A node in the TeX box model
+    """
     def __init__(self):
         self.size = 0
 
@@ -1203,21 +1176,26 @@
         return 0.0
 
     def shrink(self):
-        """Shrinks one level smaller.  There are only three levels of sizes,
-        after which things will no longer get smaller."""
+        """
+        Shrinks one level smaller.  There are only three levels of
+        sizes, after which things will no longer get smaller.
+        """
         self.size += 1
 
     def grow(self):
-        """Grows one level larger.  There is no limit to how big something
-        can get."""
+        """
+        Grows one level larger.  There is no limit to how big
+        something can get.
+        """
         self.size -= 1
 
     def render(self, x, y):
         pass
 
 class Box(Node):
-    """Represents any node with a physical location.
-    node135"""
+    """
+    Represents any node with a physical location.
+    """
     def __init__(self, width, height, depth):
         Node.__init__(self)
         self.width  = width
@@ -1255,15 +1233,16 @@
         Box.__init__(self, width, 0., 0.)
 
 class Char(Node):
-    """Represents a single character.  Unlike TeX, the font
-    information and metrics are stored with each Char to make it
-    easier to lookup the font metrics when needed.  Note that TeX
-    boxes have a width, height, and depth, unlike Type1 and Truetype
-    which use a full bounding box and an advance in the x-direction.
-    The metrics must be converted to the TeX way, and the advance (if
-    different from width) must be converted into a Kern node when the
-    Char is added to its parent Hlist.
-    node134"""
+    """
+    Represents a single character.  Unlike TeX, the font information
+    and metrics are stored with each :class:`Char` to make it easier
+    to lookup the font metrics when needed.  Note that TeX boxes have
+    a width, height, and depth, unlike Type1 and Truetype which use a
+    full bounding box and an advance in the x-direction.  The metrics
+    must be converted to the TeX way, and the advance (if different
+    from width) must be converted into a :class:`Kern` node when the
+    :class:`Char` is added to its parent :class:`Hlist`.
+    """
     def __init__(self, c, state):
         Node.__init__(self)
         self.c = c
@@ -1294,9 +1273,11 @@
         return self._metrics.slanted
 
     def get_kerning(self, next):
-        """Return the amount of kerning between this and the given
+        """
+        Return the amount of kerning between this and the given
         character.  Called when characters are strung together into
-        Hlists to create Kern nodes."""
+        :class:`Hlist` to create :class:`Kern` nodes.
+        """
         advance = self._metrics.advance - self.width
         kern = 0.
         if isinstance(next, Char):
@@ -1307,7 +1288,9 @@
         return advance + kern
 
     def render(self, x, y):
-        """Render the character to the canvas"""
+        """
+        Render the character to the canvas
+        """
         self.font_output.render_glyph(
             x, y,
             self.font, self.font_class, self.c, self.fontsize, self.dpi)
@@ -1328,9 +1311,11 @@
         self.depth    *= GROW_FACTOR
 
 class Accent(Char):
-    """The font metrics need to be dealt with differently for accents,
+    """
+    The font metrics need to be dealt with differently for accents,
     since they are already offset correctly from the baseline in
-    TrueType fonts."""
+    TrueType fonts.
+    """
     def _update_metrics(self):
         metrics = self._metrics = self.font_output.get_metrics(
             self.font, self.font_class, self.c, self.fontsize, self.dpi)
@@ -1347,14 +1332,17 @@
         self._update_metrics()
 
     def render(self, x, y):
-        """Render the character to the canvas"""
+        """
+        Render the character to the canvas.
+        """
         self.font_output.render_glyph(
             x - self._metrics.xmin, y + self._metrics.ymin,
             self.font, self.font_class, self.c, self.fontsize, self.dpi)
 
 class List(Box):
-    """A list of nodes (either horizontal or vertical).
-    node135"""
+    """
+    A list of nodes (either horizontal or vertical).
+    """
     def __init__(self, elements):
         Box.__init__(self, 0., 0., 0.)
         self.shift_amount = 0.   # An arbitrary offset
@@ -1372,8 +1360,10 @@
             ' '.join([repr(x) for x in self.children]))
 
     def _determine_order(self, totals):
-        """A helper function to determine the highest order of glue
-        used by the members of this list.  Used by vpack and hpack."""
+        """
+        A helper function to determine the highest order of glue
+        used by the members of this list.  Used by vpack and hpack.
+        """
         o = 0
         for i in range(len(totals) - 1, 0, -1):
             if totals[i] != 0.0:
@@ -1411,8 +1401,9 @@
         self.glue_set     *= GROW_FACTOR
 
 class Hlist(List):
-    """A horizontal list of boxes.
-    node135"""
+    """
+    A horizontal list of boxes.
+    """
     def __init__(self, elements, w=0., m='additional', do_kern=True):
         List.__init__(self, elements)
         if do_kern:
@@ -1420,10 +1411,13 @@
         self.hpack()
 
     def kern(self):
-        """Insert Kern nodes between Chars to set kerning.  The
-        Chars themselves determine the amount of kerning they need
-        (in get_kerning), and this function just creates the linked
-        list in the correct way."""
+        """
+        Insert :class:`Kern` nodes between :class:`Char` nodes to set
+        kerning.  The :class:`Char` nodes themselves determine the
+        amount of kerning they need (in :meth:`~Char.get_kerning`),
+        and this function just creates the linked list in the correct
+        way.
+        """
         new_children = []
         num_children = len(self.children)
         if num_children:
@@ -1455,20 +1449,24 @@
 #         return 0.0
 
     def hpack(self, w=0., m='additional'):
-        """The main duty of hpack is to compute the dimensions of the
-        resulting boxes, and to adjust the glue if one of those dimensions is
-        pre-specified. The computed sizes normally enclose all of the material
-        inside the new box; but some items may stick out if negative glue is
-        used, if the box is overfull, or if a \vbox includes other boxes that
-        have been shifted left.
+        """
+        The main duty of :meth:`hpack` is to compute the dimensions of
+        the resulting boxes, and to adjust the glue if one of those
+        dimensions is pre-specified.  The computed sizes normally
+        enclose all of the material inside the new box; but some items
+        may stick out if negative glue is used, if the box is
+        overfull, or if a ``\\vbox`` includes other boxes that have
+        been shifted left.
 
-        w: specifies a width
-        m: is either 'exactly' or 'additional'.
+          - *w*: specifies a width
 
-        Thus, hpack(w, 'exactly') produces a box whose width is exactly w, 
while
-        hpack (w, 'additional') yields a box whose width is the natural width
-        plus w.  The default values produce a box with the natural width.
-        node644, node649"""
+          - *m*: is either 'exactly' or 'additional'.
+
+        Thus, ``hpack(w, 'exactly')`` produces a box whose width is
+        exactly *w*, while ``hpack(w, 'additional')`` yields a box
+        whose width is the natural width plus *w*.  The default values
+        produce a box with the natural width.
+        """
         # I don't know why these get reset in TeX.  Shift_amount is pretty
         # much useless if we do.
         #self.shift_amount = 0.
@@ -1514,25 +1512,28 @@
             self._set_glue(x, -1, total_shrink, "Underfull")
 
 class Vlist(List):
-    """A vertical list of boxes.
-    node137"""
+    """
+    A vertical list of boxes.
+    """
     def __init__(self, elements, h=0., m='additional'):
         List.__init__(self, elements)
         self.vpack()
 
     def vpack(self, h=0., m='additional', l=float(inf)):
-        """The main duty of vpack is to compute the dimensions of the
-        resulting boxes, and to adjust the glue if one of those dimensions is
-        pre-specified.
+        """
+        The main duty of :meth:`vpack` is to compute the dimensions of
+        the resulting boxes, and to adjust the glue if one of those
+        dimensions is pre-specified.
 
-        h: specifies a height
-        m: is either 'exactly' or 'additional'.
-        l: a maximum height
+          - *h*: specifies a height
+          - *m*: is either 'exactly' or 'additional'.
+          - *l*: a maximum height
 
-        Thus, vpack(h, 'exactly') produces a box whose width is exactly w, 
while
-        vpack(w, 'additional') yields a box whose width is the natural width
-        plus w.  The default values produce a box with the natural width.
-        node644, node668"""
+        Thus, ``vpack(h, 'exactly')`` produces a box whose height is
+        exactly *h*, while ``vpack(h, 'additional')`` yields a box
+        whose height is the natural height plus *h*.  The default
+        values produce a box with the natural width.
+        """
         # I don't know why these get reset in TeX.  Shift_amount is pretty
         # much useless if we do.
         # self.shift_amount = 0.
@@ -1585,13 +1586,15 @@
             self._set_glue(x, -1, total_shrink, "Underfull")
 
 class Rule(Box):
-    """A Rule node stands for a solid black rectangle; it has width,
-    depth, and height fields just as in an Hlist. However, if any of these
-    dimensions is inf, the actual value will be determined by running the
-    rule up to the boundary of the innermost enclosing box. This is called
-    a "running dimension." The width is never running in an Hlist; the
-    height and depth are never running in a Vlist.
-    node138"""
+    """
+    A :class:`Rule` node stands for a solid black rectangle; it has
+    *width*, *depth*, and *height* fields just as in an
+    :class:`Hlist`. However, if any of these dimensions is inf, the
+    actual value will be determined by running the rule up to the
+    boundary of the innermost enclosing box. This is called a "running
+    dimension." The width is never running in an :class:`Hlist`; the
+    height and depth are never running in a :class:`Vlist`.
+    """
     def __init__(self, width, height, depth, state):
         Box.__init__(self, width, height, depth)
         self.font_output = state.font_output
@@ -1600,7 +1603,9 @@
         self.font_output.render_rect_filled(x, y, x + w, y + h)
 
 class Hrule(Rule):
-    """Convenience class to create a horizontal rule."""
+    """
+    Convenience class to create a horizontal rule.
+    """
     def __init__(self, state):
         thickness = state.font_output.get_underline_thickness(
             state.font, state.fontsize, state.dpi)
@@ -1608,18 +1613,21 @@
         Rule.__init__(self, inf, height, depth, state)
 
 class Vrule(Rule):
-    """Convenience class to create a vertical rule."""
+    """
+    Convenience class to create a vertical rule.
+    """
     def __init__(self, state):
         thickness = state.font_output.get_underline_thickness(
             state.font, state.fontsize, state.dpi)
         Rule.__init__(self, thickness, inf, inf, state)
 
 class Glue(Node):
-    """Most of the information in this object is stored in the underlying
-    GlueSpec class, which is shared between multiple glue objects.  (This
+    """
+    Most of the information in this object is stored in the underlying
+    :class:`GlueSpec` class, which is shared between multiple glue objects.  
(This
     is a memory optimization which probably doesn't matter anymore, but it's
     easier to stick to what TeX does.)
-    node149, node152"""
+    """
     def __init__(self, glue_type, copy=False):
         Node.__init__(self)
         self.glue_subtype   = 'normal'
@@ -1647,7 +1655,9 @@
             self.glue_spec.width *= GROW_FACTOR
 
 class GlueSpec(object):
-    """node150, node151"""
+    """
+    See :class:`Glue`.
+    """
     def __init__(self, width=0., stretch=0., stretch_order=0, shrink=0., 
shrink_order=0):
         self.width         = width
         self.stretch       = stretch
@@ -1709,26 +1719,32 @@
         Glue.__init__(self, 'ss')
 
 class HCentered(Hlist):
-    """A convenience class to create an Hlist whose contents are centered
-    within its enclosing box."""
+    """
+    A convenience class to create an :class:`Hlist` whose contents are
+    centered within its enclosing box.
+    """
     def __init__(self, elements):
         Hlist.__init__(self, [SsGlue()] + elements + [SsGlue()],
                        do_kern=False)
 
 class VCentered(Hlist):
-    """A convenience class to create an Vlist whose contents are centered
-    within its enclosing box."""
+    """
+    A convenience class to create a :class:`Vlist` whose contents are
+    centered within its enclosing box.
+    """
     def __init__(self, elements):
         Vlist.__init__(self, [SsGlue()] + elements + [SsGlue()])
 
 class Kern(Node):
-    """A Kern node has a width field to specify a (normally negative)
-    amount of spacing. This spacing correction appears in horizontal lists
-    between letters like A and V when the font designer said that it looks
-    better to move them closer together or further apart. A kern node can
-    also appear in a vertical list, when its 'width' denotes additional
-    spacing in the vertical direction.
-    node155"""
+    """
+    A :class:`Kern` node has a width field to specify a (normally
+    negative) amount of spacing. This spacing correction appears in
+    horizontal lists between letters like A and V when the font
+    designer said that it looks better to move them closer together or
+    further apart. A kern node can also appear in a vertical list,
+    when its *width* denotes additional spacing in the vertical
+    direction.
+    """
     def __init__(self, width):
         Node.__init__(self)
         self.width = width
@@ -1746,11 +1762,13 @@
         self.width *= GROW_FACTOR
 
 class SubSuperCluster(Hlist):
-    """This class is a sort of hack to get around that fact that this
-    code doesn't parse to an mlist and then an hlist, but goes directly
-    to hlists.  This lets us store enough information in the hlist itself,
-    namely the nucleas, sub- and super-script, such that if another script
-    follows that needs to be attached, it can be reconfigured on the fly."""
+    """
+    :class:`SubSuperCluster` is a sort of hack to get around that fact
+    that this code do a two-pass parse like TeX.  This lets us store
+    enough information in the hlist itself, namely the nucleus, sub-
+    and super-script, such that if another script follows that needs
+    to be attached, it can be reconfigured on the fly.
+    """
     def __init__(self):
         self.nucleus = None
         self.sub = None
@@ -1758,11 +1776,13 @@
         Hlist.__init__(self, [])
 
 class AutoHeightChar(Hlist):
-    """A class that will create a character as close to the given height
-    and depth as possible.  When using a font with multiple height versions
-    of some characters (such as the BaKoMa fonts), the correct glyph will
-    be selected, otherwise this will always just return a scaled version
-    of the glyph."""
+    """
+    :class:`AutoHeightChar` will create a character as close to the
+    given height and depth as possible.  When using a font with
+    multiple height versions of some characters (such as the BaKoMa
+    fonts), the correct glyph will be selected, otherwise this will
+    always just return a scaled version of the glyph.
+    """
     def __init__(self, c, height, depth, state, always=False):
         alternatives = state.font_output.get_sized_alternatives_for_symbol(
             state.font, c)
@@ -1784,11 +1804,13 @@
         self.shift_amount = shift
 
 class AutoWidthChar(Hlist):
-    """A class that will create a character as close to the given width
-    as possible.  When using a font with multiple width versions
-    of some characters (such as the BaKoMa fonts), the correct glyph will
-    be selected, otherwise this will always just return a scaled version
-    of the glyph."""
+    """
+    :class:`AutoWidthChar` will create a character as close to the
+    given width as possible.  When using a font with multiple width
+    versions of some characters (such as the BaKoMa fonts), the
+    correct glyph will be selected, otherwise this will always just
+    return a scaled version of the glyph.
+    """
     def __init__(self, c, width, state, always=False, char_class=Char):
         alternatives = state.font_output.get_sized_alternatives_for_symbol(
             state.font, c)
@@ -1808,13 +1830,15 @@
         self.width = char.width
 
 class Ship(object):
-    """Once the boxes have been set up, this sends them to output.
-    Since boxes can be inside of boxes inside of boxes, the main
-    work of Ship is done by two mutually recursive routines, hlist_out
-    and vlist_out , which traverse the Hlists and Vlists inside of
-    horizontal and vertical boxes.  The global variables used in TeX to
-    store state as it processes have become member variables here.
-    node592."""
+    """
+    Once the boxes have been set up, this sends them to output.  Since
+    boxes can be inside of boxes inside of boxes, the main work of
+    :class:`Ship` is done by two mutually recursive routines,
+    :meth:`hlist_out` and :meth:`vlist_out`, which traverse the
+    :class:`Hlist` nodes and :class:`Vlist` nodes inside of horizontal
+    and vertical boxes.  The global variables used in TeX to store
+    state as it processes have become member variables here.
+    """
     def __call__(self, ox, oy, box):
         self.max_push    = 0 # Deepest nesting of push commands so far
         self.cur_s       = 0
@@ -1959,6 +1983,9 @@
 # PARSER
 
 def Error(msg):
+    """
+    Helper class to raise parser errors.
+    """
     def raise_error(s, loc, toks):
         raise ParseFatalException(msg + "\n" + s)
 
@@ -1967,6 +1994,14 @@
     return empty
 
 class Parser(object):
+    """
+    This is the pyparsing-based parser for math expressions.  It
+    actually parses full strings *containing* math expressions, in
+    that raw text may also appear outside of pairs of ``$``.
+
+    The grammar is based directly on that in TeX, though it cuts a few
+    corners.
+    """
     _binary_operators = set(r'''
       + *
       \pm             \sqcap                   \rhd
@@ -2198,11 +2233,20 @@
         self.clear()
 
     def clear(self):
+        """
+        Clear any state before parsing.
+        """
         self._expr = None
         self._state_stack = None
         self._em_width_cache = {}
 
     def parse(self, s, fonts_object, fontsize, dpi):
+        """
+        Parse expression *s* using the given *fonts_object* for
+        output, at the given *fontsize* and *dpi*.
+
+        Returns the parse tree of :class:`Node` instances.
+        """
         self._state_stack = [self.State(fonts_object, 'default', 'rm', 
fontsize, dpi)]
         try:
             self._expression.parseString(s)
@@ -2219,6 +2263,12 @@
     # is pushed and popped accordingly.  The current state always
     # exists in the top element of the stack.
     class State(object):
+        """
+        Stores the state of the parser.
+
+        States are pushed and popped from a stack as necessary, and
+        the "current" state is always at the top of the stack.
+        """
         def __init__(self, font_output, font, font_class, fontsize, dpi):
             self.font_output = font_output
             self._font = font
@@ -2243,12 +2293,22 @@
         font = property(_get_font, _set_font)
 
     def get_state(self):
+        """
+        Get the current :class:`State` of the parser.
+        """
         return self._state_stack[-1]
 
     def pop_state(self):
+        """
+        Pop a :class:`State` off of the stack.
+        """
         self._state_stack.pop()
 
     def push_state(self):
+        """
+        Push a new :class:`State` onto the stack which is just a copy
+        of the current state.
+        """
         self._state_stack.append(self.get_state().copy())
 
     def finish(self, s, loc, toks):
@@ -2674,14 +2734,6 @@
 # MAIN
 
 class MathTextParser(object):
-    """
-    Parse the math expression s, return the (bbox, fonts) tuple needed
-    to render it.
-
-    fontsize must be in points
-
-    return is width, height, fonts
-    """
     _parser = None
 
     _backend_mapping = {
@@ -2701,10 +2753,23 @@
         }
 
     def __init__(self, output):
+        """
+        Create a MathTextParser for the given backend *output*.
+        """
         self._output = output.lower()
         self._cache = maxdict(50)
 
     def parse(self, s, dpi = 72, prop = None):
+        """
+        Parse the given math expression *s* at the given *dpi*.  If
+        *prop* is provided, it is a
+        :class:`~matplotlib.font_manager.FontProperties` object
+        specifying the "default" font to use in the math expression,
+        used for all non-math text.
+
+        The results are cached, so multiple calls to :meth:`parse`
+        with the same expression should be fast.
+        """
         if prop is None:
             prop = FontProperties()
         cacheKey = (s, dpi, hash(prop))
@@ -2712,7 +2777,7 @@
         if result is not None:
             return result
 
-        if self._output == 'PS' and rcParams['ps.useafm']:
+        if self._output == 'ps' and rcParams['ps.useafm']:
             font_output = StandardPsFonts(prop)
         else:
             backend = self._backend_mapping[self._output]()
@@ -2748,6 +2813,15 @@
 
     def to_mask(self, texstr, dpi=120, fontsize=14):
         """
+        *texstr*
+            A valid mathtext string, eg r'IQ: $\sigma_i=15$'
+
+        *dpi*
+            The dots-per-inch to render the text
+
+        *fontsize*
+            The font size in points
+
         Returns a tuple (*array*, *depth*)
 
           - *array* is an NxM uint8 alpha ubyte mask array of
@@ -2755,15 +2829,6 @@
 
           - depth is the offset of the baseline from the bottom of the
             image in pixels.
-
-        ''texstr''
-            A valid mathtext string, eg r'IQ: $\sigma_i=15$'
-
-        ''dpi''
-            The dots-per-inch to render the text
-
-        ''fontsize''
-            The font size in points
         """
         assert(self._output=="bitmap")
         prop = FontProperties(size=fontsize)
@@ -2774,27 +2839,25 @@
 
     def to_rgba(self, texstr, color='black', dpi=120, fontsize=14):
         """
-        Returns a tuple (*array*, *depth*)
+        *texstr*
+            A valid mathtext string, eg r'IQ: $\sigma_i=15$'
 
-          - *array* is an NxMx4 RGBA array of ubyte rasterized tex.
+        *color*
+            Any matplotlib color argument
 
-          - depth is the offset of the baseline from the bottom of the
-            image in pixels.
+        *dpi*
+            The dots-per-inch to render the text
 
-        Returns a tuple (array, depth), where depth is the offset of
-        the baseline from the bottom of the image.
+        *fontsize*
+            The font size in points
 
-        ''texstr''
-            A valid mathtext string, eg r'IQ: $\sigma_i=15$'
+        Returns a tuple (*array*, *depth*)
 
-        ''color''
-            A valid matplotlib color argument
+          - *array* is an NxM uint8 alpha ubyte mask array of
+            rasterized tex.
 
-        ''dpi''
-            The dots-per-inch to render the text
-
-        ''fontsize''
-            The font size in points
+          - depth is the offset of the baseline from the bottom of the
+            image in pixels.
         """
         x, depth = self.to_mask(texstr, dpi=dpi, fontsize=fontsize)
 
@@ -2813,22 +2876,24 @@
         Returns the offset of the baseline from the bottom of the
         image in pixels.
 
-        ''filename''
+        *filename*
             A writable filename or fileobject
 
-        ''texstr''
+        *texstr*
             A valid mathtext string, eg r'IQ: $\sigma_i=15$'
 
-        ''color''
+        *color*
             A valid matplotlib color argument
 
-        ''dpi''
+        *dpi*
             The dots-per-inch to render the text
 
-        ''fontsize''
+        *fontsize*
             The font size in points
 
-            """
+        Returns the offset of the baseline from the bottom of the
+        image in pixels.
+        """
 
         rgba, depth = self.to_rgba(texstr, color=color, dpi=dpi, 
fontsize=fontsize)
         numrows, numcols, tmp = rgba.shape
@@ -2840,16 +2905,15 @@
         Returns the offset of the baseline from the bottom of the
         image in pixels.
 
-        ''texstr''
+        *texstr*
             A valid mathtext string, eg r'IQ: $\sigma_i=15$'
 
-        ''dpi''
+        *dpi*
             The dots-per-inch to render the text
 
-        ''fontsize''
+        *fontsize*
             The font size in points
-
-            """
+        """
         assert(self._output=="bitmap")
         prop = FontProperties(size=fontsize)
         ftimage, depth = self.parse(texstr, dpi=dpi, prop=prop)


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to