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

Skip to content

Commit 546f1e1

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 7673002 commit 546f1e1

File tree

4 files changed

+35
-70
lines changed

4 files changed

+35
-70
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: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,31 @@
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 forseeable 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 atexit
109119
from collections import MutableMapping
110120
import contextlib
111-
import distutils.version
112-
import distutils.sysconfig
121+
from distutils.version import LooseVersion
113122
import functools
114123
import io
115124
import inspect
@@ -135,17 +144,16 @@
135144
136145
""")
137146

147+
from six.moves.urllib.request import urlopen
148+
from six.moves import reload_module as reload
149+
138150
# cbook must import matplotlib only within function
139151
# definitions, so it is safe to import from it here.
140152
from . import cbook
141-
from matplotlib.cbook import (
153+
from .cbook import (
142154
_backports, mplDeprecation, dedent, get_label, sanitize_sequence)
143-
from matplotlib.compat import subprocess
144-
from matplotlib.rcsetup import defaultParams, validate_backend, cycler
145-
146-
import numpy
147-
from six.moves.urllib.request import urlopen
148-
from six.moves import reload_module as reload
155+
from .compat import subprocess
156+
from .rcsetup import defaultParams, validate_backend, cycler
149157

150158
# Get the version from the _version.py versioneer file. For a git checkout,
151159
# this is computed based on the number of commits since the last tag.
@@ -190,41 +198,11 @@ def compare_versions(a, b):
190198
a = a.decode('ascii')
191199
if isinstance(b, bytes):
192200
b = b.decode('ascii')
193-
a = distutils.version.LooseVersion(a)
194-
b = distutils.version.LooseVersion(b)
195-
return a >= b
201+
return LooseVersion(a) >= LooseVersion(b)
196202
else:
197203
return False
198204

199205

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

setupext.py

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

124124

125-
def extract_versions():
126-
"""
127-
Extracts version values from the main matplotlib __init__.py and
128-
returns them as a dictionary.
129-
"""
130-
with open('lib/matplotlib/__init__.py') as fd:
131-
for line in fd.readlines():
132-
if (line.startswith('__version__numpy__')):
133-
exec(line.strip())
134-
return locals()
135-
136-
137125
def has_include_file(include_dirs, filename):
138126
"""
139127
Returns `True` if `filename` can be found in one of the
@@ -962,7 +950,8 @@ def include_dirs_hook():
962950
return [numpy.get_include()]
963951

964952
def check(self):
965-
min_version = extract_versions()['__version__numpy__']
953+
# Remember to keep the version in INSTALL.rst in sync.
954+
min_version = "1.7.1"
966955
try:
967956
import numpy
968957
except ImportError:
@@ -1433,6 +1422,7 @@ def check(self):
14331422
return "handled by setuptools"
14341423

14351424
def get_install_requires(self):
1425+
# Remember to keep the list in INSTALL.rst in sync.
14361426
install_requires = [
14371427
"cycler>=0.10",
14381428
"pyparsing>=2.0.1,!=2.0.4,!=2.1.2,!=2.1.6",

0 commit comments

Comments
 (0)