Skip to content

Commit 84781b4

Browse files
committed
COMPAT: blacklist numexpr=2.4.4
Closes #12489 Author: Jeff Reback <[email protected]> Closes #12511 from jreback/numexpr and squashes the following commits: bb5cb1c [Jeff Reback] COMPAT: remove boto dep check, xref #11915 bad7c0f [Jeff Reback] COMPAT: blacklist numexpr=2.4.4
1 parent eba7803 commit 84781b4

14 files changed

+126
-57
lines changed

ci/requirements-3.4_SLOW.run

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ html5lib
99
patsy
1010
beautiful-soup
1111
scipy
12-
numexpr
12+
numexpr=2.4.4
1313
pytables
1414
matplotlib
1515
lxml

ci/requirements-3.5.run

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ sqlalchemy
1818
pymysql
1919
psycopg2
2020
xarray
21+
boto
2122

2223
# incompat with conda ATM
2324
# beautiful-soup

doc/source/install.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ Recommended Dependencies
225225

226226
* `numexpr <https://github.com/pydata/numexpr>`__: for accelerating certain numerical operations.
227227
``numexpr`` uses multiple cores as well as smart chunking and caching to achieve large speedups.
228-
If installed, must be Version 2.1 or higher. Version 2.4.6 or higher on Windows is highly recommended.
228+
If installed, must be Version 2.1 or higher (excluding a buggy 2.4.4). Version 2.4.6 or higher is highly recommended.
229229

230230
* `bottleneck <http://berkeleyanalytics.com/bottleneck>`__: for accelerating certain types of ``nan``
231231
evaluations. ``bottleneck`` uses specialized cython routines to achieve large speedups.

doc/source/whatsnew/v0.18.0.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ users upgrade to this version.
1212
pandas >= 0.18.0 no longer supports compatibility with Python version 2.6
1313
and 3.3 (:issue:`7718`, :issue:`11273`)
1414

15+
.. warning::
16+
17+
``numexpr`` version 2.4.4 will now show a warning and not be used as a computation back-end for pandas because of some buggy behavior. This does not affect other versions (>= 2.1 and >= 2.4.6). (:issue:`12489`)
18+
1519
Highlights include:
1620

1721
- Moving and expanding window functions are now methods on Series and DataFrame,
@@ -1121,7 +1125,7 @@ Bug Fixes
11211125
- Bug in ``Series.resample`` using a frequency of ``Nano`` when the index is a ``DatetimeIndex`` and contains non-zero nanosecond parts (:issue:`12037`)
11221126
- Bug in resampling with ``.nunique`` and a sparse index (:issue:`12352`)
11231127
- Removed some compiler warnings (:issue:`12471`)
1124-
1128+
- Work around compat issues with ``boto`` in python 3.5 (:issue:`11915`)
11251129
- Bug in ``NaT`` subtraction from ``Timestamp`` or ``DatetimeIndex`` with timezones (:issue:`11718`)
11261130
- Bug in subtraction of ``Series`` of a single tz-aware ``Timestamp`` (:issue:`12290`)
11271131

pandas/computation/__init__.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
import warnings
3+
from distutils.version import LooseVersion
4+
5+
_NUMEXPR_INSTALLED = False
6+
7+
try:
8+
import numexpr as ne
9+
ver = ne.__version__
10+
_NUMEXPR_INSTALLED = ver >= LooseVersion('2.1')
11+
12+
# we specifically disallow 2.4.4 as
13+
# has some hard-to-diagnose bugs
14+
if ver == LooseVersion('2.4.4'):
15+
_NUMEXPR_INSTALLED = False
16+
warnings.warn(
17+
"The installed version of numexpr {ver} is not supported "
18+
"in pandas and will be not be used\n".format(ver=ver),
19+
UserWarning)
20+
21+
elif not _NUMEXPR_INSTALLED:
22+
warnings.warn(
23+
"The installed version of numexpr {ver} is not supported "
24+
"in pandas and will be not be used\nThe minimum supported "
25+
"version is 2.1\n".format(ver=ver), UserWarning)
26+
27+
except ImportError: # pragma: no cover
28+
pass
29+
30+
__all__ = ['_NUMEXPR_INSTALLED']

pandas/computation/eval.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
import warnings
77
import tokenize
88
from pandas.core import common as com
9+
from pandas.computation import _NUMEXPR_INSTALLED
910
from pandas.computation.expr import Expr, _parsers, tokenize_string
1011
from pandas.computation.scope import _ensure_scope
1112
from pandas.compat import string_types
1213
from pandas.computation.engines import _engines
13-
from distutils.version import LooseVersion
1414

1515

1616
def _check_engine(engine):
@@ -35,17 +35,11 @@ def _check_engine(engine):
3535
# that won't necessarily be import-able)
3636
# Could potentially be done on engine instantiation
3737
if engine == 'numexpr':
38-
try:
39-
import numexpr
40-
except ImportError:
41-
raise ImportError("'numexpr' not found. Cannot use "
38+
if not _NUMEXPR_INSTALLED:
39+
raise ImportError("'numexpr' is not installed or an "
40+
"unsupported version. Cannot use "
4241
"engine='numexpr' for query/eval "
4342
"if 'numexpr' is not installed")
44-
else:
45-
ne_version = numexpr.__version__
46-
if ne_version < LooseVersion('2.1'):
47-
raise ImportError("'numexpr' version is %s, "
48-
"must be >= 2.1" % ne_version)
4943

5044

5145
def _check_parser(parser):

pandas/computation/expressions.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,10 @@
99
import warnings
1010
import numpy as np
1111
from pandas.core.common import _values_from_object
12-
from distutils.version import LooseVersion
12+
from pandas.computation import _NUMEXPR_INSTALLED
1313

14-
try:
14+
if _NUMEXPR_INSTALLED:
1515
import numexpr as ne
16-
ver = ne.__version__
17-
_NUMEXPR_INSTALLED = ver >= LooseVersion('2.1')
18-
if not _NUMEXPR_INSTALLED:
19-
warnings.warn(
20-
"The installed version of numexpr {ver} is not supported "
21-
"in pandas and will be not be used\nThe minimum supported "
22-
"version is 2.1\n".format(ver=ver), UserWarning)
23-
24-
except ImportError: # pragma: no cover
25-
_NUMEXPR_INSTALLED = False
2616

2717
_TEST_MODE = None
2818
_TEST_RESULT = None
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/usr/bin/env python
2+
3+
# flake8: noqa
4+
5+
import nose
6+
from itertools import product
7+
from distutils.version import LooseVersion
8+
9+
import pandas as pd
10+
from pandas.util import testing as tm
11+
12+
from pandas.computation.engines import _engines
13+
import pandas.computation.expr as expr
14+
15+
ENGINES_PARSERS = list(product(_engines, expr._parsers))
16+
17+
18+
def test_compat():
19+
# test we have compat with our version of nu
20+
21+
from pandas.computation import _NUMEXPR_INSTALLED
22+
try:
23+
import numexpr as ne
24+
ver = ne.__version__
25+
if ver == LooseVersion('2.4.4'):
26+
assert not _NUMEXPR_INSTALLED
27+
elif ver < LooseVersion('2.1'):
28+
with tm.assert_produces_warning(UserWarning,
29+
check_stacklevel=False):
30+
assert not _NUMEXPR_INSTALLED
31+
else:
32+
assert _NUMEXPR_INSTALLED
33+
34+
except ImportError:
35+
raise nose.SkipTest("not testing numexpr version compat")
36+
37+
38+
def test_invalid_numexpr_version():
39+
for engine, parser in ENGINES_PARSERS:
40+
yield check_invalid_numexpr_version, engine, parser
41+
42+
43+
def check_invalid_numexpr_version(engine, parser):
44+
def testit():
45+
a, b = 1, 2
46+
res = pd.eval('a + b', engine=engine, parser=parser)
47+
tm.assert_equal(res, 3)
48+
49+
if engine == 'numexpr':
50+
try:
51+
import numexpr as ne
52+
except ImportError:
53+
raise nose.SkipTest("no numexpr")
54+
else:
55+
if ne.__version__ < LooseVersion('2.1'):
56+
with tm.assertRaisesRegexp(ImportError, "'numexpr' version is "
57+
".+, must be >= 2.1"):
58+
testit()
59+
elif ne.__version__ == LooseVersion('2.4.4'):
60+
raise nose.SkipTest("numexpr version==2.4.4")
61+
else:
62+
testit()
63+
else:
64+
testit()
65+
66+
67+
if __name__ == '__main__':
68+
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],
69+
exit=False)

pandas/computation/tests/test_eval.py

-27
Original file line numberDiff line numberDiff line change
@@ -1782,33 +1782,6 @@ def test_name_error_exprs():
17821782
yield check_name_error_exprs, engine, parser
17831783

17841784

1785-
def check_invalid_numexpr_version(engine, parser):
1786-
def testit():
1787-
a, b = 1, 2
1788-
res = pd.eval('a + b', engine=engine, parser=parser)
1789-
tm.assert_equal(res, 3)
1790-
1791-
if engine == 'numexpr':
1792-
try:
1793-
import numexpr as ne
1794-
except ImportError:
1795-
raise nose.SkipTest("no numexpr")
1796-
else:
1797-
if ne.__version__ < LooseVersion('2.1'):
1798-
with tm.assertRaisesRegexp(ImportError, "'numexpr' version is "
1799-
".+, must be >= 2.1"):
1800-
testit()
1801-
else:
1802-
testit()
1803-
else:
1804-
testit()
1805-
1806-
1807-
def test_invalid_numexpr_version():
1808-
for engine, parser in ENGINES_PARSERS:
1809-
yield check_invalid_numexpr_version, engine, parser
1810-
1811-
18121785
def check_invalid_local_variable_reference(engine, parser):
18131786
tm.skip_if_no_ne(engine)
18141787

pandas/core/datetools.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
"""A collection of random tools for dealing with dates in Python"""
22

3-
from pandas.tseries.tools import * # noqa
4-
from pandas.tseries.offsets import * # noqa
5-
from pandas.tseries.frequencies import * # noqa
3+
# flake8: noqa
4+
5+
from pandas.tseries.tools import *
6+
from pandas.tseries.offsets import *
7+
from pandas.tseries.frequencies import *
68

79
day = DateOffset()
810
bday = BDay()

pandas/core/format.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from pandas.core.index import Index, MultiIndex, _ensure_index
1111
from pandas import compat
1212
from pandas.compat import (StringIO, lzip, range, map, zip, reduce, u,
13-
OrderedDict)
13+
OrderedDict, unichr)
1414
from pandas.util.terminal import get_terminal_size
1515
from pandas.core.config import get_option, set_option
1616
from pandas.io.common import _get_handle, UnicodeWriter, _expand_user

pandas/io/common.py

+4
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ def readline(self):
146146
except ImportError:
147147
# boto is only needed for reading from S3.
148148
pass
149+
except TypeError:
150+
# boto/boto3 issues
151+
# GH11915
152+
pass
149153

150154

151155
def _is_url(url):

pandas/util/clipboard.py

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
4646
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4747

48+
# flake8: noqa
4849

4950
import platform
5051
import os

pandas/util/print_versions.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ def show_versions(as_json=False):
9191
("sqlalchemy", lambda mod: mod.__version__),
9292
("pymysql", lambda mod: mod.__version__),
9393
("psycopg2", lambda mod: mod.__version__),
94-
("jinja2", lambda mod: mod.__version__)
94+
("jinja2", lambda mod: mod.__version__),
95+
("boto", lambda mod: mod.__version__)
9596
]
9697

9798
deps_blob = list()

0 commit comments

Comments
 (0)