diff --git a/doc/conf.py b/doc/conf.py index 54e90d21745a..4fd5209eed89 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -58,7 +58,7 @@ # General substitutions. project = 'Matplotlib' -copyright = '2013 John Hunter, Darren Dale, Eric Firing, Michael Droettboom and the matplotlib development team' +copyright = '2002 - 2012 John Hunter, Darren Dale, Eric Firing, Michael Droettboom and the matplotlib development team; 2012 - 2013 The matplotlib development team' # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. diff --git a/doc/devel/documenting_mpl.rst b/doc/devel/documenting_mpl.rst index f43977cb4008..27309e4b4e2c 100644 --- a/doc/devel/documenting_mpl.rst +++ b/doc/devel/documenting_mpl.rst @@ -351,7 +351,7 @@ An example save command to generate a movie looks like this ani.save('double_pendulum.mp4', fps=15) -Contact John Hunter for the login password to upload youtube videos of +Contact Michael Droettboom for the login password to upload youtube videos of google docs to the mplgithub account. .. _referring-to-mpl-docs: diff --git a/doc/users/license.rst b/doc/users/license.rst index acf401c29e46..073bf6a3bc33 100644 --- a/doc/users/license.rst +++ b/doc/users/license.rst @@ -13,10 +13,86 @@ licenses. Non-BSD compatible licenses (eg LGPL) are acceptable in matplotlib toolkits. For a discussion of the motivations behind the licencing choice, see :ref:`license-discussion`. +Copyright Policy +================ + +John Hunter began matplotlib around 2003. Since shortly before his +passing in 2012, Michael Droettboom has been the lead maintainer of +matplotlib, but, as has always been the case, matplotlib is the work +of many. + +Prior to July of 2013, and the 1.3.0 release, the copyright of the +source code was held by John Hunter. As of July 2013, and the 1.3.0 +release, matplotlib has moved to a shared copyright model. + +matplotlib uses a shared copyright model. Each contributor maintains +copyright over their contributions to matplotlib. But, it is important to +note that these contributions are typically only changes to the +repositories. Thus, the matplotlib source code, in its entirety, is not +the copyright of any single person or institution. Instead, it is the +collective copyright of the entire matplotlib Development Team. If +individual contributors want to maintain a record of what +changes/contributions they have specific copyright on, they should +indicate their copyright in the commit message of the change, when +they commit the change to one of the matplotlib repositories. + +The Matplotlib Development Team is the set of all contributors to the +matplotlib project. A full list can be obtained from the git version +control logs. License agreement for matplotlib |version| ============================================== +1. This LICENSE AGREEMENT is between the Matplotlib Development Team +("MDT"), and the Individual or Organization ("Licensee") accessing and +otherwise using matplotlib software in source or binary form and its +associated documentation. + +. Subject to the terms and conditions of this License Agreement, MDT +hereby grants Licensee a nonexclusive, royalty-free, world-wide license +to reproduce, analyze, test, perform and/or display publicly, prepare +derivative works, distribute, and otherwise use matplotlib |version| +alone or in any derivative version, provided, however, that MDT's +License Agreement and MDT's notice of copyright, i.e., "Copyright (c) +2012-2013 Matplotlib Development Team; All Rights Reserved" are retained in +matplotlib |version| alone or in any derivative version prepared by +Licensee. + +3. In the event Licensee prepares a derivative work that is based on or +incorporates matplotlib |version| or any part thereof, and wants to +make the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to matplotlib |version|. + +4. MDT is making matplotlib |version| available to Licensee on an "AS +IS" basis. MDT MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, MDT MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB |version| +WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + +5. MDT SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB +|version| FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR +LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING +MATPLOTLIB |version|, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF +THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between MDT and +Licensee. This License Agreement does not grant permission to use MDT +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using matplotlib |version|, +Licensee agrees to be bound by the terms and conditions of this License +Agreement. + +License agreement for matplotlib versions prior to 1.3.0 +======================================================== + 1. This LICENSE AGREEMENT is between John D. Hunter ("JDH"), and the Individual or Organization ("Licensee") accessing and otherwise using matplotlib software in source or binary form and its associated diff --git a/examples/pylab_examples/scatter_rotate_symbol.py b/examples/pylab_examples/scatter_rotate_symbol.py new file mode 100644 index 000000000000..02adc62a0fc2 --- /dev/null +++ b/examples/pylab_examples/scatter_rotate_symbol.py @@ -0,0 +1,15 @@ +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.markers import TICKRIGHT + +rx, ry = 3., 1. +area = rx * ry * np.pi +angles = np.linspace(0., 360., 30.) + +x, y, sizes, colors = np.random.rand(4, 30) +sizes *= 20**2. + +plt.scatter(x, y, sizes, colors, marker="o",zorder=2) +plt.scatter(x, y, 2.5*sizes, colors, marker=TICKRIGHT, angles=angles, zorder=2) + +plt.show() diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index ab7ffe4ee7b1..9c8baa90bbe2 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -718,11 +718,11 @@ def matplotlib_fname(): fname == os.path.join( get_home(), '.matplotlib', 'matplotlibrc')): warnings.warn( - "Found matplotlib configuration in ~/.matplotlib. " + "Found matplotlib configuration in ~/.matplotlib/. " "To conform with the XDG base directory standard, " "this configuration location has been deprecated " - "on Linux, and the new location is now %r. Please " - "move your configuration there to ensure that " + "on Linux, and the new location is now %r/matplotlib/. " + "Please move your configuration there to ensure that " "matplotlib will continue to find it in the future." % _get_xdg_config_dir()) return fname diff --git a/lib/matplotlib/afm.py b/lib/matplotlib/afm.py index ba14a6f7a042..75c7491a3f96 100644 --- a/lib/matplotlib/afm.py +++ b/lib/matplotlib/afm.py @@ -1,23 +1,27 @@ """ This is a python interface to Adobe Font Metrics Files. Although a -number of other python implementations exist (and may be more complete -than mine) I decided not to go with them because either they were -either +number of other python implementations exist, and may be more complete +than this, it was decided not to go with them because they were +either: 1) copyrighted or used a non-BSD compatible license - 2) had too many dependencies and I wanted a free standing lib + 2) had too many dependencies and a free standing lib was needed - 3) Did more than I needed and it was easier to write my own than - figure out how to just get what I needed from theirs + 3) Did more than needed and it was easier to write afresh rather than + figure out how to get just what was needed. -It is pretty easy to use, and requires only built-in python libs:: +It is pretty easy to use, and requires only built-in python libs: - >>> from afm import AFM - >>> fh = open('ptmr8a.afm') - >>> afm = AFM(fh) + >>> from matplotlib import rcParams + >>> import os.path + >>> afm_fname = os.path.join(rcParams['datapath'], + ... 'fonts', 'afm', 'ptmr8a.afm') + >>> + >>> from matplotlib.afm import AFM + >>> afm = AFM(open(afm_fname)) >>> afm.string_width_height('What the heck?') - (6220.0, 683) + (6220.0, 694) >>> afm.get_fontname() 'Times-Roman' >>> afm.get_kern_dist('A', 'f') @@ -26,12 +30,7 @@ -92.0 >>> afm.get_bbox_char('!') [130, -9, 238, 676] - >>> afm.get_bbox_font() - [-168, -218, 1000, 898] - -AUTHOR: - John D. Hunter """ from __future__ import print_function @@ -549,14 +548,4 @@ def get_vertical_stem_width(self): Return the standard vertical stem width as float, or *None* if not specified in AFM file. """ - return self._header.get(b'StdVW', None) - - -if __name__ == '__main__': - #pathname = '/usr/local/lib/R/afm/' - pathname = '/usr/local/share/fonts/afms/adobe' - - for fname in os.listdir(pathname): - with open(os.path.join(pathname, fname)) as fh: - afm = AFM(fh) - w, h = afm.string_width_height('John Hunter is the Man!') + return self._header.get(b'StdVW', None) \ No newline at end of file diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index e72c0ba38bd7..100850224b00 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3134,7 +3134,7 @@ def dopatch(xs, ys): medians=medians, fliers=fliers) @docstring.dedent_interpd - def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None, + def scatter(self, x, y, s=20, c='b', marker='o', angles=0, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, **kwargs): """ @@ -3162,6 +3162,9 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None, See `~matplotlib.markers` for more information on the different styles of markers scatter supports. + angles : scalar or array_like, shape (n, ), optional, default: 0 + degrees counter clock-wise from X axis + cmap : `~matplotlib.colors.Colormap`, optional, default: None A `~matplotlib.colors.Colormap` instance or registered name. `cmap` is only used if `c` is an array of floats. If None, @@ -3222,6 +3225,7 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None, raise ValueError("x and y must be the same size") s = np.ma.ravel(s) # This doesn't have to match x, y in size. + angles = np.ma.ravel(angles) # This doesn't have to match x, y in size. c_is_stringy = is_string_like(c) or is_sequence_of_strings(c) if not c_is_stringy: @@ -3229,7 +3233,7 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None, if c.size == x.size: c = np.ma.ravel(c) - x, y, s, c = cbook.delete_masked_points(x, y, s, c) + x, y, s, c, angles = cbook.delete_masked_points(x, y, s, c, angles) scales = s # Renamed for readability below. @@ -3265,7 +3269,7 @@ def scatter(self, x, y, s=20, c='b', marker='o', cmap=None, norm=None, edgecolors = 'face' collection = mcoll.PathCollection( - (path,), scales, + (path,), scales, angles, facecolors=colors, edgecolors=edgecolors, linewidths=linewidths, diff --git a/lib/matplotlib/backends/backend_wxagg.py b/lib/matplotlib/backends/backend_wxagg.py index 5b301a045f04..80276b30d7b0 100644 --- a/lib/matplotlib/backends/backend_wxagg.py +++ b/lib/matplotlib/backends/backend_wxagg.py @@ -1,20 +1,3 @@ -""" - - backend_wxagg.py - - A wxPython backend for Agg. This uses the GUI widgets written by - Jeremy O'Donoghue (jeremy@o-donoghue.com) and the Agg backend by John - Hunter (jdhunter@ace.bsd.uchicago.edu) - - Copyright (C) 2003-5 Jeremy O'Donoghue, John Hunter, Illinois Institute of - Technology - - - License: This work is licensed under the matplotlib license( PSF - compatible). A copy should be included with this source code. - -""" - from __future__ import division, print_function import matplotlib from matplotlib.figure import Figure @@ -26,6 +9,7 @@ draw_if_interactive, show, Toolbar, backend_version import wx + class FigureFrameWxAgg(FigureFrameWx): def get_canvas(self, fig): return FigureCanvasWxAgg(self, -1, fig) @@ -40,6 +24,7 @@ def _get_toolbar(self, statbar): toolbar = None return toolbar + class FigureCanvasWxAgg(FigureCanvasAgg, FigureCanvasWx): """ The FigureCanvas contains the figure and does event handling. @@ -105,6 +90,7 @@ def print_figure(self, filename, *args, **kwargs): if self._isDrawn: self.draw() + class NavigationToolbar2WxAgg(NavigationToolbar2Wx): def get_canvas(self, frame, fig): return FigureCanvasWxAgg(frame, -1, fig) @@ -200,5 +186,4 @@ def _WX28_clipped_agg_as_bitmap(agg, bbox): srcDC.SelectObject(wx.NullBitmap) destDC.SelectObject(wx.NullBitmap) - return destBmp - + return destBmp \ No newline at end of file diff --git a/lib/matplotlib/cbook.py b/lib/matplotlib/cbook.py index f44bcb867b2a..771b9654f7e6 100644 --- a/lib/matplotlib/cbook.py +++ b/lib/matplotlib/cbook.py @@ -1617,7 +1617,7 @@ class Grouper(object): >>> grp.join(b, c) >>> grp.join(d, e) >>> sorted(map(tuple, grp)) - [(d, e), (a, b, c)] + [(a, b, c), (d, e)] >>> grp.joined(a, b) True >>> grp.joined(a, c) diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index a40546da2770..eb5ac7f5ef99 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -687,34 +687,97 @@ class PathCollection(Collection): This is the most basic :class:`Collection` subclass. """ @docstring.dedent_interpd - def __init__(self, paths, sizes=None, **kwargs): + def __init__(self, paths, sizes=None, angles=None, **kwargs): """ *paths* is a sequence of :class:`matplotlib.path.Path` instances. + *sizes* is an array of length 1 or more, size in points^2 + + *angles* is an array of length 1 or more, degrees + counter clock-wise from X axis + %(Collection)s """ Collection.__init__(self, **kwargs) self.set_paths(paths) self._sizes = sizes + self._angles = angles + self._normalize_parameters() + + def _normalize_parameters(self): + """ + Check the sizes and array dimention to make them the same size + Needed for drawing them efficiently + """ + if (self._sizes is not None + and self._angles is not None + and self._sizes.size != self._angles.size): + + # Make sizes array and angles array same size + if self._sizes.size > self._angles.size: + self._angles = np.ma.resize(self._angles, self._sizes.shape) + else: + self._sizes = np.ma.resize(self._sizes, self._angles.shape) def set_paths(self, paths): + """ + update the paths sequence + """ self._paths = paths def get_paths(self): + """ + return the paths sequence + """ return self._paths + def set_sizes(self, sizes): + """ + update sizes array check array size + """ + self._sizes = sizes + self._normalize_parameters() + def get_sizes(self): + """ + return the sizes array + """ return self._sizes + def set_angles(self, angles): + """ + update angles array check array size + """ + self._angles = angles + self._normalize_parameters() + + def get_angles(self): + """ + return the angle array + """ + return self._angles + @allow_rasterization def draw(self, renderer): - if self._sizes is not None: + if self._sizes is not None and self._angles is not None: + _sizes = np.sqrt(self._sizes) * self.figure.dpi / 72.0 + _angles = np.deg2rad(self._angles) self._transforms = [ - transforms.Affine2D().scale( - (np.sqrt(x) * self.figure.dpi / 72.0)) - for x in self._sizes] + transforms.Affine2D().scale(s).rotate(a) + for s, a in zip(_sizes, _angles)] + elif self._sizes is not None: + _sizes = np.sqrt(self._sizes) * self.figure.dpi / 72.0 + self._transforms = [ + transforms.Affine2D().scale(s) + for s in _sizes] + elif self._angles is not None: + _angles = np.deg2rad(self._angles) + self._transforms = [ + transforms.Affine2D().rotate(a) + for a in _angles] + return Collection.draw(self, renderer) diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py index 743fccc2bc25..b21f6ddbfb68 100644 --- a/lib/matplotlib/offsetbox.py +++ b/lib/matplotlib/offsetbox.py @@ -16,6 +16,7 @@ from __future__ import print_function +import warnings import matplotlib.transforms as mtransforms import matplotlib.artist as martist import matplotlib.text as mtext @@ -1098,6 +1099,12 @@ def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, **kwargs): other keyword parameters of AnchoredOffsetbox are also allowed. """ + propkeys = prop.keys() + badkwargs = ('ha', 'horizontalalignment', 'va', 'verticalalignment') + if set(badkwargs) & set(propkeys): + warnings.warn("Mixing horizontalalignment or verticalalignment " + "with AnchoredText is not supported.") + self.txt = TextArea(s, textprops=prop, minimumdescent=False) fp = self.txt._text.get_fontproperties() diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index ed8e157ba3c0..cddfe9c5f8f9 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -3075,9 +3075,9 @@ def quiverkey(*args, **kw): # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost @_autogen_docstring(Axes.scatter) -def scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None, vmin=None, - vmax=None, alpha=None, linewidths=None, verts=None, hold=None, - **kwargs): +def scatter(x, y, s=20, c='b', marker='o', angles=0, cmap=None, norm=None, + vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, + hold=None, **kwargs): ax = gca() # allow callers to override the hold state by passing hold=True|False washold = ax.ishold() @@ -3085,9 +3085,10 @@ def scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None, vmin=None, if hold is not None: ax.hold(hold) try: - ret = ax.scatter(x, y, s=s, c=c, marker=marker, cmap=cmap, norm=norm, - vmin=vmin, vmax=vmax, alpha=alpha, - linewidths=linewidths, verts=verts, **kwargs) + ret = ax.scatter(x, y, s=s, c=c, marker=marker, angles=angles, + cmap=cmap, norm=norm, vmin=vmin, vmax=vmax, + alpha=alpha, linewidths=linewidths, verts=verts, + **kwargs) draw_if_interactive() finally: ax.hold(washold) @@ -3213,7 +3214,7 @@ def step(x, y, *args, **kwargs): @_autogen_docstring(Axes.streamplot) def streamplot(x, y, u, v, density=1, linewidth=None, color=None, cmap=None, norm=None, arrowsize=1, arrowstyle='-|>', minlength=0.1, - transform=None, hold=None, zorder=1): + transform=None, zorder=1, hold=None): ax = gca() # allow callers to override the hold state by passing hold=True|False washold = ax.ishold() diff --git a/lib/matplotlib/stackplot.py b/lib/matplotlib/stackplot.py index 99942a340b6e..c7a70971c6b2 100644 --- a/lib/matplotlib/stackplot.py +++ b/lib/matplotlib/stackplot.py @@ -43,6 +43,11 @@ def stackplot(axes, x, *args, **kwargs): Returns *r* : A list of :class:`~matplotlib.collections.PolyCollection`, one for each element in the stacked area plot. + + Note that :class:`~matplotlib.legend.Legend` does not support + :class:`~matplotlib.collections.PolyCollection` objects. To create a + legend on a stackplot, use a proxy artist: + http://matplotlib.org/users/legend_guide.html#using-proxy-artist """ if len(args) == 1: diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index 120b4843e436..3cc2416dddec 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -3,6 +3,8 @@ from matplotlib.testing.decorators import cleanup, image_comparison from matplotlib import pyplot as plt +import re + @cleanup def test_contour_shape_1d_valid(): @@ -97,14 +99,18 @@ def test_contour_shape_mismatch_4(): ax.contour(b, g, z) except TypeError as exc: print exc.args[0] - assert exc.args[0] == 'Shape of x does not match that of z: ' + \ - 'found (9, 9) instead of (9, 10).' + assert re.match( + r'Shape of x does not match that of z: ' + + r'found \(9L?, 9L?\) instead of \(9L?, 10L?\)\.', + exc.args[0]) is not None try: ax.contour(g, b, z) except TypeError as exc: - assert exc.args[0] == 'Shape of y does not match that of z: ' + \ - 'found (9, 9) instead of (9, 10).' + assert re.match( + r'Shape of y does not match that of z: ' + + r'found \(9L?, 9L?\) instead of \(9L?, 10L?\)\.', + exc.args[0]) is not None @cleanup @@ -157,23 +163,23 @@ def test_given_colors_levels_and_extends(): _, axes = plt.subplots(2, 4) data = np.arange(12).reshape(3, 4) - + colors = ['red', 'yellow', 'pink', 'blue', 'black'] levels = [2, 4, 8, 10] - + for i, ax in enumerate(axes.flatten()): plt.sca(ax) - + filled = i % 2 == 0. extend = ['neither', 'min', 'max', 'both'][i // 2] - + if filled: last_color = -1 if extend in ['min', 'max'] else None plt.contourf(data, colors=colors[:last_color], levels=levels, extend=extend) else: last_level = -1 if extend == 'both' else None plt.contour(data, colors=colors, levels=levels[:last_level], extend=extend) - + plt.colorbar() diff --git a/lib/matplotlib/tests/test_simplification.py b/lib/matplotlib/tests/test_simplification.py index f5247ce17ad4..fc9afb899aa0 100644 --- a/lib/matplotlib/tests/test_simplification.py +++ b/lib/matplotlib/tests/test_simplification.py @@ -152,7 +152,7 @@ def test_start_with_moveto(): verts = np.fromstring(decodebytes(data), dtype=' bufpair = _get_output_buffer(); #if PY3K - Py::Object ret = Py::asObject(Py_BuildValue("lly#", rowsOut, colsOut, + Py::Object ret = Py::asObject(Py_BuildValue("nny#", rowsOut, colsOut, bufpair.first, colsOut * rowsOut * 4)); #else - Py::Object ret = Py::asObject(Py_BuildValue("lls#", rowsOut, colsOut, + Py::Object ret = Py::asObject(Py_BuildValue("nns#", rowsOut, colsOut, bufpair.first, colsOut * rowsOut * 4)); #endif @@ -272,7 +272,7 @@ Image::color_conv(const Py::Tuple& args) } #endif - PyObject* o = Py_BuildValue("llN", rowsOut, colsOut, py_buffer); + PyObject* o = Py_BuildValue("nnN", rowsOut, colsOut, py_buffer); return Py::asObject(o); } @@ -290,7 +290,7 @@ Image::buffer_rgba(const Py::Tuple& args) args.verify_length(0); int row_len = colsOut * 4; - PyObject* o = Py_BuildValue("lls#", rowsOut, colsOut, + PyObject* o = Py_BuildValue("nns#", rowsOut, colsOut, rbufOut, row_len * rowsOut); return Py::asObject(o); } diff --git a/src/agg_py_transforms.cpp b/src/agg_py_transforms.cpp index 739512605b99..7e85ec1b7608 100644 --- a/src/agg_py_transforms.cpp +++ b/src/agg_py_transforms.cpp @@ -31,8 +31,10 @@ py_to_agg_transformation_matrix(PyObject* obj, bool errors = true) try { matrix = (PyArrayObject*) PyArray_FromObject(obj, PyArray_DOUBLE, 2, 2); - if (!matrix) + if (!matrix) { + PyErr_Clear(); throw std::exception(); + } } catch (...) { diff --git a/tests.py b/tests.py index a78c9bb2b194..677d18ff6b06 100755 --- a/tests.py +++ b/tests.py @@ -1,9 +1,13 @@ #!/usr/bin/env python # # This allows running the matplotlib tests from the command line: e.g. -# python tests.py -v -d -# See http://somethingaboutorange.com/mrl/projects/nose/1.0.0/usage.html -# for options. +# +# $ python tests.py -v -d +# +# The arguments are identical to the arguments accepted by nosetests. +# +# See https://nose.readthedocs.org/ for a detailed description of +# these options. import os import time