Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a8541e1

Browse files
committed
Check dependencies at runtime as declared in setup.py.
The goal is to list the requirements exactly once in code (in setupext.py) and once in the docs (in INSTALL.rst). Instead of manually importing and checking that (python) dependencies are installed with the correct versions, rely on pkg_resources, which allows automatically keeping things in sync with setupext, as well as correctly check e.g. the complex version requirements on pyparsing. Remove the overly complex way to specify the minimum numpy version. Add comments reminding to update INSTALL.rst when the requirements are changed in setupext.py; reorder dependencies in INSTALL.rst in a more logical order. Remove unneeded reference to MATLAB being a registered trademark. Note that if you are running Matplotlib from source by manipulating PYTHONPATH, then it will not appear to pkg_resources. In this case, there is no check for other dependencies (you are assumed to be responsible enough for that). Conversely, Matplotlib will fail to import if it is installed into site-packages but some dependency (six, etc.) is only available in PYTHONPATH instead of being correctly installed. I think this is acceptable (or we could just completely drop the import checks and let bad installs fail with normal ImportErrors).
1 parent c01f862 commit a8541e1

File tree

4 files changed

+58
-69
lines changed

4 files changed

+58
-69
lines changed

INSTALL.rst

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,20 @@ e.g., if the header of some required library is in
137137
Dependencies
138138
------------
139139

140-
Matplotlib requires a large number of dependencies:
140+
Matplotlib requires the following dependencies:
141141

142142
* `Python <https://www.python.org/downloads/>`_ (>= 3.5)
143-
* `NumPy <http://www.numpy.org>`_ (>= |minimum_numpy_version|)
144-
* `setuptools <https://setuptools.readthedocs.io/en/latest/>`__
143+
* `setuptools <https://setuptools.readthedocs.io/en/latest/>`_
144+
* `NumPy <http://www.numpy.org>`_ (>= 1.10.0)
145+
* `cycler <http://matplotlib.org/cycler/>`_ (>= 0.10.0)
145146
* `dateutil <https://pypi.python.org/pypi/python-dateutil>`_ (>= 2.1)
146-
* `pyparsing <https://pyparsing.wikispaces.com/>`__
147-
* `libpng <http://www.libpng.org>`__ (>= 1.2)
148-
* `pytz <http://pytz.sourceforge.net/>`__
149-
* FreeType (>= 2.3)
150-
* `cycler <http://matplotlib.org/cycler/>`__ (>= 0.10.0)
151-
* `six <https://pypi.python.org/pypi/six>`_
152147
* `kiwisolver <https://github.com/nucleic/kiwi>`__ (>= 1.0.0)
148+
* `pyparsing <https://pyparsing.wikispaces.com/>`_ (>= 2.1.7; some older
149+
versions may work)
150+
* `pytz <http://pytz.sourceforge.net/>`_
151+
* `six <https://pypi.python.org/pypi/six>`_ (>= 1.10)
152+
* `FreeType <https://www.freetype.org>`_ (>= 2.3)
153+
* `libpng <http://www.libpng.org>`_ (>= 1.2)
153154

154155
Optionally, you can also install a number of packages to enable better user
155156
interface toolkits. See :ref:`what-is-a-backend` for more details on the

doc/conf.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,6 @@ def _check_deps():
323323
# documentation
324324
autoclass_content = 'both'
325325

326-
rst_epilog = """
327-
.. |minimum_numpy_version| replace:: %s
328-
""" % matplotlib.__version__numpy__
329-
330326
texinfo_documents = [
331327
("contents", 'matplotlib', 'Matplotlib Documentation',
332328
'John Hunter@*Darren Dale@*Eric Firing@*Michael Droettboom@*'

lib/matplotlib/__init__.py

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,25 @@
9494
9595
matplotlib was initially written by John D. Hunter (1968-2012) and is now
9696
developed and maintained by a host of others.
97-
98-
Occasionally the internal documentation (python docstrings) will refer
99-
to MATLAB&reg;, a registered trademark of The MathWorks, Inc.
100-
10197
"""
10298
# NOTE: This file must remain Python 2 compatible for the foreseeable future,
10399
# to ensure that we error out properly for existing editable installs.
104100
from __future__ import absolute_import, division, print_function
105101

102+
import pkg_resources
103+
104+
try:
105+
pkg_resources.get_distribution("matplotlib")
106+
except pkg_resources.DistributionNotFound:
107+
# Running from source -- you're on your own.
108+
pass
109+
else:
110+
try:
111+
# Check that dependencies are correctly installed.
112+
pkg_resources.require("matplotlib")
113+
except pkg_resources.ResolutionError as e:
114+
raise ImportError("Matplotlib requires {}".format(e.req))
115+
106116
import six
107117

108118
import sys
@@ -120,8 +130,7 @@
120130
import atexit
121131
from collections import MutableMapping
122132
import contextlib
123-
import distutils.version
124-
import distutils.sysconfig
133+
from distutils.version import LooseVersion
125134
import functools
126135
import io
127136
import inspect
@@ -137,16 +146,39 @@
137146
import tempfile
138147
import warnings
139148

149+
if sys.version_info < (3, 5): # noqa: E402
150+
raise ImportError("""
151+
Matplotlib 3.0+ does not support Python 2.x, 3.0, 3.1, 3.2, 3.3, or 3.4.
152+
Beginning with Matplotlib 3.0, Python 3.5 and above is required.
153+
154+
See Matplotlib `INSTALL.rst` file for more information:
155+
156+
https://github.com/matplotlib/matplotlib/blob/master/INSTALL.rst
157+
158+
""")
159+
160+
if sys.version_info < (3, 5): # noqa: E402
161+
raise ImportError("""
162+
Matplotlib 3.0+ does not support Python 2.x, 3.0, 3.1, 3.2, 3.3, or 3.4.
163+
Beginning with Matplotlib 3.0, Python 3.5 and above is required.
164+
165+
See Matplotlib `INSTALL.rst` file for more information:
166+
167+
https://github.com/matplotlib/matplotlib/blob/master/INSTALL.rst
168+
169+
""")
170+
171+
from six.moves.urllib.request import urlopen
172+
from six.moves import reload_module as reload
173+
174+
import numpy
175+
140176
# cbook must import matplotlib only within function
141177
# definitions, so it is safe to import from it here.
142178
from . import cbook
143-
from matplotlib.cbook import (
179+
from .cbook import (
144180
_backports, mplDeprecation, dedent, get_label, sanitize_sequence)
145-
from matplotlib.rcsetup import defaultParams, validate_backend, cycler
146-
147-
import numpy
148-
from six.moves.urllib.request import urlopen
149-
from six.moves import reload_module as reload
181+
from .rcsetup import defaultParams, validate_backend, cycler
150182

151183
# Get the version from the _version.py versioneer file. For a git checkout,
152184
# this is computed based on the number of commits since the last tag.
@@ -191,41 +223,11 @@ def compare_versions(a, b):
191223
a = a.decode('ascii')
192224
if isinstance(b, bytes):
193225
b = b.decode('ascii')
194-
a = distutils.version.LooseVersion(a)
195-
b = distutils.version.LooseVersion(b)
196-
return a >= b
226+
return LooseVersion(a) >= LooseVersion(b)
197227
else:
198228
return False
199229

200230

201-
try:
202-
import dateutil
203-
except ImportError:
204-
raise ImportError("Matplotlib requires dateutil")
205-
206-
207-
if not compare_versions(six.__version__, '1.10'):
208-
raise ImportError(
209-
"Matplotlib requires six>=1.10; you have %s" % six.__version__)
210-
211-
212-
try:
213-
import pyparsing
214-
except ImportError:
215-
raise ImportError("Matplotlib requires pyparsing")
216-
else:
217-
if not compare_versions(pyparsing.__version__, '2.0.1'):
218-
raise ImportError(
219-
"Matplotlib requires pyparsing>=2.0.1; you have %s"
220-
% pyparsing.__version__)
221-
222-
223-
if not compare_versions(numpy.__version__, __version__numpy__):
224-
raise ImportError(
225-
"Matplotlib requires numpy>=%s; you have %s" % (
226-
__version__numpy__, numpy.__version__))
227-
228-
229231
if not hasattr(sys, 'argv'): # for modpython
230232
sys.argv = [str('modpython')]
231233

setupext.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,18 +107,6 @@ def get_win32_compiler():
107107
win32_compiler = get_win32_compiler()
108108

109109

110-
def extract_versions():
111-
"""
112-
Extracts version values from the main matplotlib __init__.py and
113-
returns them as a dictionary.
114-
"""
115-
with open('lib/matplotlib/__init__.py') as fd:
116-
for line in fd.readlines():
117-
if (line.startswith('__version__numpy__')):
118-
exec(line.strip())
119-
return locals()
120-
121-
122110
def has_include_file(include_dirs, filename):
123111
"""
124112
Returns `True` if `filename` can be found in one of the
@@ -925,7 +913,8 @@ def include_dirs_hook():
925913
return [numpy.get_include()]
926914

927915
def check(self):
928-
min_version = extract_versions()['__version__numpy__']
916+
# Remember to keep the version in INSTALL.rst in sync.
917+
min_version = "1.7.1"
929918
try:
930919
import numpy
931920
except ImportError:
@@ -1391,6 +1380,7 @@ def check(self):
13911380
return "handled by setuptools"
13921381

13931382
def get_install_requires(self):
1383+
# Remember to keep the list in INSTALL.rst in sync.
13941384
install_requires = [
13951385
"cycler>=0.10",
13961386
"pyparsing>=2.0.1,!=2.0.4,!=2.1.2,!=2.1.6",

0 commit comments

Comments
 (0)