Skip to content

Commit a3dde2b

Browse files
numpy: Require NumPy >= 1.15.0
ubuntu: Provide NumPy Remove apt dependencies on NumPy
1 parent 890a37e commit a3dde2b

21 files changed

+213
-174
lines changed

bindings/pydrake/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ drake_py_library(
4343
# We use `common:_init_py` to avoid dependency cycles.
4444
"//bindings:bazel_workaround_4594_libdrake_py",
4545
"//bindings/pydrake/common:_init_py",
46+
"//bindings/pydrake/util:compatibility_py",
4647
"//bindings/pydrake/util:deprecation_py",
48+
"@numpy_py",
4749
],
4850
)
4951

bindings/pydrake/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030
# We specifically load `common` prior to loading any other pydrake modules,
3131
# in order to get assertion configuration done as early as possible.
3232
from . import common
33+
from .util.compatibility import check_required_numpy_version
3334
from .util.deprecation import ModuleShim
3435

3536
__all__ = ['common', 'getDrakePath']
37+
check_required_numpy_version()
3638
common.set_assertion_failure_to_throw_exception()
3739

3840

bindings/pydrake/autodiffutils_py.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace pydrake {
1717
PYBIND11_MODULE(autodiffutils, m) {
1818
m.doc() = "Bindings for Eigen AutoDiff Scalars";
1919

20-
// Install NumPy warning filtres.
20+
// Install NumPy warning filters.
2121
// N.B. This may interfere with other code, but until that is a confirmed
2222
// issue, we should aggressively try to avoid these warnings.
2323
py::module::import("pydrake.util.deprecation")

bindings/pydrake/symbolic_py.cc

-4
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ PYBIND11_MODULE(symbolic, m) {
3131
py::module::import("pydrake.util.deprecation")
3232
.attr("install_numpy_warning_filters")();
3333

34-
// Install NumPy formatters patch.
35-
py::module::import("pydrake.util.compatibility")
36-
.attr("maybe_patch_numpy_formatters")();
37-
3834
m.doc() =
3935
"Symbolic variable, variables, monomial, expression, polynomial, and "
4036
"formula";

bindings/pydrake/util/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ drake_py_library(
5959
name = "module_py",
6060
srcs = ["__init__.py"],
6161
imports = PACKAGE_INFO.py_imports,
62+
deps = ["@numpy_py"],
6263
)
6364

6465
drake_py_library(
@@ -187,6 +188,7 @@ drake_py_library(
187188
name = "compatibility_py",
188189
srcs = ["compatibility.py"],
189190
deps = [
191+
":deprecation_py",
190192
":module_py",
191193
],
192194
)
+19-47
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,30 @@
11
"""Contains routines to monkey patch or provide alternatives to upstream code
2-
which may need changes for compatibility.
2+
which may need changes for compatibility, or check versions.
33
"""
44

55
import numpy as np
6+
from numpy.lib import NumpyVersion
67

7-
_numpy_version = np.lib.NumpyVersion(np.version.version)
8-
_patches = {
9-
'numpy_formatters': {
10-
'applied': False,
11-
'required': _numpy_version < np.lib.NumpyVersion('1.13.0'),
12-
},
13-
}
8+
from pydrake.util.deprecation import _warn_deprecated
149

1510

16-
def _defer_callable_type(cls):
17-
# Makes a type, which is meant to purely callable, and defers its
18-
# construction until it needs to be called.
11+
def check_required_numpy_version(_actual=np.version.version):
12+
"""Fails fast if a minimum version of NumPy is not present.
1913
20-
class Deferred(object):
21-
def __init__(self, *args, **kwargs):
22-
self._args = args
23-
self._kwargs = kwargs
24-
self._obj = None
25-
26-
def _get_obj(self):
27-
if self._obj is None:
28-
self._obj = cls(*self._args, **self._kwargs)
29-
return self._obj
30-
31-
def __call__(self, *args, **kwargs):
32-
return self._get_obj().__call__(*args, **kwargs)
33-
34-
return Deferred
14+
pydrake requires NumPy >= 0.15.0 namely for the following patches:
15+
https://github.com/numpy/numpy/pull/10898
16+
https://github.com/numpy/numpy/pull/11076
17+
"""
18+
actual = NumpyVersion(_actual)
19+
minimum = NumpyVersion('1.15.0')
20+
if actual < minimum:
21+
raise RuntimeError(
22+
"pydrake requires numpy >= {}, but only {} is present".format(
23+
minimum.vstring, actual.vstring))
3524

3625

3726
def maybe_patch_numpy_formatters():
38-
"""Required to permit printing of symbolic array types in NumPy < 1.13.0.
39-
40-
See #8729 for more information.
41-
"""
42-
# Provides version-dependent monkey-patch which effectively achieves a
43-
# portion of https://github.com/numpy/numpy/pull/8963
44-
patch = _patches['numpy_formatters']
45-
if not patch['required']:
46-
return
47-
if patch['applied']:
48-
return
49-
module = np.core.arrayprint
50-
defer_callable_types = [
51-
'IntegerFormat',
52-
'FloatFormat',
53-
]
54-
for name in defer_callable_types:
55-
original = getattr(module, name)
56-
deferred = _defer_callable_type(original)
57-
setattr(module, name, deferred)
58-
patch['applied'] = True
27+
"""Deprecated functionality."""
28+
_warn_deprecated(
29+
"`maybe_patch_numpy_formatters` is no longer needed, and will "
30+
"be removed after 2019/01", stacklevel=3)
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,21 @@
11
import pydrake.util.compatibility as mut
22

3-
import numpy as np
43
import unittest
4+
import warnings
55

6-
numpy_formatters = mut._patches["numpy_formatters"]
7-
8-
# TODO(eric.cousineau): Try to reproduce NumPy formatter patch with mock types.
9-
# Even with creating a `MockSymbol` type which returns a `MockFormula` which
10-
# raises an error on `__nonzero__`, I could not get the error relevant to #8729
11-
# to trigger via `np.maximum.reduce` (but could trigger the error via
12-
# `np.max`).
6+
import numpy as np
137

148

159
class TestCompatibility(unittest.TestCase):
16-
@unittest.skipIf(not numpy_formatters["required"], "Patch not required")
1710
def test_numpy_formatters(self):
18-
# Ensure that the expected types have been patched with the `Deferred`
19-
# type.
20-
expect_deferred = [
21-
'IntegerFormat',
22-
'FloatFormat',
23-
]
24-
# Before patching.
25-
self.assertFalse(numpy_formatters["applied"])
26-
module = np.core.arrayprint
27-
for name in expect_deferred:
28-
self.assertNotIn("Deferred", str(getattr(module, name)))
29-
# Apply patch.
30-
mut.maybe_patch_numpy_formatters()
31-
self.assertTrue(numpy_formatters["applied"])
32-
for name in expect_deferred:
33-
self.assertIn("Deferred", str(getattr(module, name)))
11+
# Call for backwards compatibility.
12+
with warnings.catch_warnings(record=True) as w:
13+
mut.maybe_patch_numpy_formatters()
14+
self.assertEqual(len(w), 1)
15+
16+
def test_numpy_version(self):
17+
# This should pass nominally.
18+
mut.check_required_numpy_version()
19+
# Mock in an old version.
20+
with self.assertRaises(RuntimeError):
21+
mut.check_required_numpy_version(_actual="1.11.0")

setup/ubuntu/16.04/binary_distribution/packages.txt

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ libyaml-cpp0.5v5
3232
python
3333
python-lxml
3434
python-matplotlib
35-
python-numpy
3635
python-pydot
3736
python-scipy
3837
python-six

setup/ubuntu/18.04/binary_distribution/packages.txt

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ libyaml-cpp0.5v5
3232
python
3333
python-lxml
3434
python-matplotlib
35-
python-numpy
3635
python-pydot
3736
python-scipy
3837
python-six

tools/BUILD.bazel

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ py_binary(
3333
"//tools/workspace/drake_visualizer:stub_pydrake",
3434
"//tools/workspace/drake_visualizer/plugin",
3535
"@drake_visualizer//:drake_visualizer_python_deps",
36+
# TODO(eric.cousineau): Move `numpy_py` dependency to a `vtk` Python
37+
# library.
38+
"@numpy_py",
3639
"@optitrack_driver//lcmtypes:py_optitrack_lcmtypes",
3740
],
3841
)

tools/skylark/pybind.bzl

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def pybind_py_library(
7373
visibility = visibility,
7474
)
7575

76+
# Ensure that we're always using our custom NumPy version.
77+
if "@numpy_py" not in py_deps:
78+
py_deps = py_deps + ["@numpy_py"]
79+
7680
# Add Python library.
7781
py_library_rule(
7882
name = py_name,

tools/workspace/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ _DRAKE_EXTERNAL_PACKAGE_INSTALLS = ["@%s//:install" % p for p in [
3636
"lcmtypes_robotlocomotion",
3737
"meshcat",
3838
"meshcat_python",
39+
"numpy_py",
3940
"octomap",
4041
"osqp",
4142
"pybind11",

tools/workspace/default.bzl

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ load("@drake//tools/workspace/meshcat_python:repository.bzl", "meshcat_python_re
4343
load("@drake//tools/workspace/mosek:repository.bzl", "mosek_repository")
4444
load("@drake//tools/workspace/net_sf_jchart2d:repository.bzl", "net_sf_jchart2d_repository") # noqa
4545
load("@drake//tools/workspace/nlopt:repository.bzl", "nlopt_repository")
46-
load("@drake//tools/workspace/numpy:repository.bzl", "numpy_repository")
46+
load("@drake//tools/workspace/numpy_py:repository.bzl", "numpy_py_repository")
4747
load("@drake//tools/workspace/octomap:repository.bzl", "octomap_repository")
4848
load("@drake//tools/workspace/optitrack_driver:repository.bzl", "optitrack_driver_repository") # noqa
4949
load("@drake//tools/workspace/org_apache_xmlgraphics_commons:repository.bzl", "org_apache_xmlgraphics_commons_repository") # noqa
@@ -168,8 +168,8 @@ def add_default_repositories(excludes = [], mirrors = DEFAULT_MIRRORS):
168168
net_sf_jchart2d_repository(name = "net_sf_jchart2d", mirrors = mirrors)
169169
if "nlopt" not in excludes:
170170
nlopt_repository(name = "nlopt")
171-
if "numpy" not in excludes:
172-
numpy_repository(name = "numpy")
171+
if "numpy_py" not in excludes:
172+
numpy_py_repository(name = "numpy_py", mirrors = mirrors)
173173
if "octomap" not in excludes:
174174
octomap_repository(name = "octomap", mirrors = mirrors)
175175
if "optitrack_driver" not in excludes:

tools/workspace/mirrors.bzl

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ DEFAULT_MIRRORS = {
4949
"https://drake-mirror.csail.mit.edu/pypi/{package}/{package}-{version}.tar.gz", # noqa
5050
"https://s3.amazonaws.com/drake-mirror/pypi/{package}/{package}-{version}.tar.gz", # noqa
5151
],
52+
"pypi-general": [
53+
"https://files.pythonhosted.org/packages/{hash_path}/{filename}", # noqa
54+
],
5255
"vtk": [
5356
"https://drake-packages.csail.mit.edu/vtk/{archive}",
5457
"https://s3.amazonaws.com/drake-packages/vtk/{archive}",

tools/workspace/numpy/BUILD.bazel

-8
This file was deleted.

tools/workspace/numpy/repository.bzl

-83
This file was deleted.

tools/workspace/numpy_py/BUILD.bazel

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# -*- python -*-
2+
3+
load("//tools/lint:lint.bzl", "add_lint_tests")
4+
load(
5+
"//tools/skylark:drake_py.bzl",
6+
"drake_py_unittest",
7+
)
8+
9+
add_lint_tests()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# -*- python -*-
2+
3+
load(
4+
"@drake//tools/install:install.bzl",
5+
"install",
6+
)
7+
8+
licenses([
9+
"notice", # BSD-2-Clause AND BSD-3-Clause AND MIT AND Python-2.0
10+
"unencumbered", # Public-Domain
11+
])
12+
13+
# Interpret `numpy` sources as data to simplify handling.
14+
filegroup(
15+
name = "data",
16+
srcs = glob(["numpy/**/*"]),
17+
visibility = ["//visibility:private"],
18+
)
19+
20+
py_library(
21+
name = "numpy_py",
22+
data = [":data"],
23+
imports = ["."],
24+
visibility = ["//visibility:public"],
25+
)
26+
27+
install(
28+
name = "install",
29+
data = [":data"],
30+
data_dest = "lib/python2.7/site-packages",
31+
visibility = ["//visibility:public"],
32+
)

0 commit comments

Comments
 (0)