diff --git a/.travis.yml b/.travis.yml index 6022a59c9a32..afdcb299fcb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -106,9 +106,6 @@ script: # Travis VM to run out of memory (since so many copies of inkscape and # ghostscript are running at the same time). - echo Testing using $NPROC processes - # Generate the font caches in a single process before starting the - # multiple processes - - python -c "from matplotlib import font_manager" - | if [[ $BUILD_DOCS == false ]]; then export MPL_REPO_DIR=$PWD # needed for pep8-conformance test of the examples diff --git a/LICENSE/LICENSE_CONDA b/LICENSE/LICENSE_CONDA new file mode 100644 index 000000000000..8794a6d484af --- /dev/null +++ b/LICENSE/LICENSE_CONDA @@ -0,0 +1,51 @@ +Except where noted below, conda is released under the following terms: + +(c) 2012 Continuum Analytics, Inc. / http://continuum.io +All Rights Reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Continuum Analytics, Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL CONTINUUM ANALYTICS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Exceptions +========== + +versioneer.py is Public Domain + +The ProgressBar package is released under the following terms: + +# progressbar - Text progress bar library for Python. +# Copyright (c) 2005 Nilton Volpato +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \ No newline at end of file diff --git a/lib/matplotlib/cbook.py b/lib/matplotlib/cbook.py index 18ef6b793c2b..58cb04dc960d 100644 --- a/lib/matplotlib/cbook.py +++ b/lib/matplotlib/cbook.py @@ -2550,3 +2550,54 @@ def get_label(y, default_name): else: def _putmask(a, mask, values): return np.copyto(a, values, where=mask) + + +class Locked(object): + """ + Context manager to handle locks. + + Based on code from conda. + + (c) 2012-2013 Continuum Analytics, Inc. / http://continuum.io + All Rights Reserved + + conda is distributed under the terms of the BSD 3-clause license. + Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause. + """ + def __init__(self, path): + LOCKFN = '.matplotlib_lock' + self.path = path + self.end = "-" + str(os.getpid()) + self.lock_path = os.path.join(self.path, LOCKFN + self.end) + self.pattern = os.path.join(self.path, LOCKFN + '-*') + self.remove = True + + def __enter__(self): + retries = 10 + sleeptime = 1 + while retries: + files = glob.glob(self.pattern) + if files and not files[0].endswith(self.end): + time.sleep(sleeptime) + sleeptime *= 2 + retries -= 1 + else: + break + else: + raise RuntimeError(lockstr) + + if not files: + try: + os.makedirs(self.lock_path) + except OSError: + pass + else: # PID lock already here --- someone else will remove it. + self.remove = False + + def __exit__(self, exc_type, exc_value, traceback): + if self.remove: + for path in self.lock_path, self.path: + try: + os.rmdir(path) + except OSError: + pass diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index c84fa0e4dc1c..7bba3b8ae3ae 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -1405,10 +1405,9 @@ def findfont(prop, fontext='ttf'): else: _fmcache = None - if not 'TRAVIS' in os.environ: - cachedir = get_cachedir() - if cachedir is not None: - _fmcache = os.path.join(cachedir, 'fontList.json') + cachedir = get_cachedir() + if cachedir is not None: + _fmcache = os.path.join(cachedir, 'fontList.json') fontManager = None @@ -1419,9 +1418,13 @@ def findfont(prop, fontext='ttf'): def _rebuild(): global fontManager + fontManager = FontManager() + if _fmcache: - json_dump(fontManager, _fmcache) + with cbook.Locked(cachedir): + json_dump(fontManager, _fmcache) + verbose.report("generated new fontManager") if _fmcache: diff --git a/tests.py b/tests.py index ed5f3b4f6f27..70dfeb37974c 100755 --- a/tests.py +++ b/tests.py @@ -21,13 +21,6 @@ from matplotlib.testing.noseclasses import KnownFailure from matplotlib import default_test_modules -from matplotlib import font_manager -# Make sure the font caches are created before starting any possibly -# parallel tests -if font_manager._fmcache is not None: - while not os.path.exists(font_manager._fmcache): - time.sleep(0.5) - plugins = [KnownFailure, attrib.Plugin] # Nose doesn't automatically instantiate all of the plugins in the