Skip to content

Commit c708c79

Browse files
committed
COMPAT: compat for python 3.5, pandas-dev#11097
- update install / compat docs for 3.5 - use visit_Call based on the version of python - skip if html5lib is not installed in test_data - bug in nose causes deprecation warning in some pytables tests - remove superfluous socket timeout
1 parent 6bdf948 commit c708c79

File tree

11 files changed

+104
-26
lines changed

11 files changed

+104
-26
lines changed

.travis.yml

+10-10
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ matrix:
4343
- CLIPBOARD_GUI=gtk2
4444
- BUILD_TYPE=conda
4545
- DOC_BUILD=true # if rst files were changed, build docs in parallel with tests
46-
- python: 3.3
47-
env:
48-
- JOB_NAME: "33_nslow"
49-
- NOSE_ARGS="not slow and not disabled"
50-
- FULL_DEPS=true
51-
- CLIPBOARD=xsel
52-
- BUILD_TYPE=conda
5346
- python: 3.4
5447
env:
5548
- JOB_NAME: "34_nslow"
@@ -64,6 +57,13 @@ matrix:
6457
- FULL_DEPS=true
6558
- CLIPBOARD=xsel
6659
- BUILD_TYPE=conda
60+
- python: 3.3
61+
env:
62+
- JOB_NAME: "33_nslow"
63+
- NOSE_ARGS="not slow and not disabled"
64+
- FULL_DEPS=true
65+
- CLIPBOARD=xsel
66+
- BUILD_TYPE=conda
6767
- python: 2.7
6868
env:
6969
- JOB_NAME: "27_slow"
@@ -104,10 +104,10 @@ matrix:
104104
- BUILD_TYPE=pydata
105105
- PANDAS_TESTING_MODE="deprecate"
106106
allow_failures:
107-
- python: 3.5
107+
- python: 3.3
108108
env:
109-
- JOB_NAME: "35_nslow"
110-
- NOSE_ARGS="not slow and not network and not disabled"
109+
- JOB_NAME: "33_nslow"
110+
- NOSE_ARGS="not slow and not disabled"
111111
- FULL_DEPS=true
112112
- CLIPBOARD=xsel
113113
- BUILD_TYPE=conda

ci/requirements-3.5.txt

+12
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,15 @@ cython
1010
scipy
1111
numexpr
1212
pytables
13+
html5lib
14+
lxml
15+
16+
# currently causing some warnings
17+
#sqlalchemy
18+
#pymysql
19+
#psycopg2
20+
21+
# not available from conda
22+
#beautiful-soup
23+
#bottleneck
24+
#matplotlib

doc/source/install.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Instructions for installing from source,
1818
Python version support
1919
----------------------
2020

21-
Officially Python 2.6, 2.7, 3.3, and 3.4.
21+
Officially Python 2.6, 2.7, 3.3, 3.4, and 3.5
2222

2323
Installing pandas
2424
-----------------

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Highlights include:
6464
- Support for reading SAS xport files, see :ref:`here <whatsnew_0170.enhancements.sas_xport>`
6565
- Documentation comparing SAS to *pandas*, see :ref:`here <compare_with_sas>`
6666
- Removal of the automatic TimeSeries broadcasting, deprecated since 0.8.0, see :ref:`here <whatsnew_0170.prior_deprecations>`
67+
- Compatibility with Python 3.5
6768

6869
See the :ref:`v0.17.0 Whatsnew <whatsnew_0170>` overview for an extensive list
6970
of all enhancements and bugs that have been fixed in 0.17.0.

doc/source/whatsnew/v0.17.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Highlights include:
4949
- Support for reading SAS xport files, see :ref:`here <whatsnew_0170.enhancements.sas_xport>`
5050
- Documentation comparing SAS to *pandas*, see :ref:`here <compare_with_sas>`
5151
- Removal of the automatic TimeSeries broadcasting, deprecated since 0.8.0, see :ref:`here <whatsnew_0170.prior_deprecations>`
52+
- Compatibility with Python 3.5 (:issue:`11097`)
5253

5354
Check the :ref:`API Changes <whatsnew_0170.api>` and :ref:`deprecations <whatsnew_0170.deprecations>` before updating.
5455

pandas/compat/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
import sys
3737
import types
3838

39-
PY3 = (sys.version_info[0] >= 3)
4039
PY2 = sys.version_info[0] == 2
41-
40+
PY3 = (sys.version_info[0] >= 3)
41+
PY35 = (sys.version_info >= (3, 5))
4242

4343
try:
4444
import __builtin__ as builtins

pandas/computation/expr.py

+55-1
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,54 @@ def visit_Attribute(self, node, **kwargs):
516516

517517
raise ValueError("Invalid Attribute context {0}".format(ctx.__name__))
518518

519-
def visit_Call(self, node, side=None, **kwargs):
519+
def visit_Call_35(self, node, side=None, **kwargs):
520+
""" in 3.5 the starargs attribute was changed to be more flexible, #11097 """
521+
522+
if isinstance(node.func, ast.Attribute):
523+
res = self.visit_Attribute(node.func)
524+
elif not isinstance(node.func, ast.Name):
525+
raise TypeError("Only named functions are supported")
526+
else:
527+
try:
528+
res = self.visit(node.func)
529+
except UndefinedVariableError:
530+
# Check if this is a supported function name
531+
try:
532+
res = FuncNode(node.func.id)
533+
except ValueError:
534+
# Raise original error
535+
raise
536+
537+
if res is None:
538+
raise ValueError("Invalid function call {0}".format(node.func.id))
539+
if hasattr(res, 'value'):
540+
res = res.value
541+
542+
if isinstance(res, FuncNode):
543+
544+
new_args = [ self.visit(arg) for arg in node.args ]
545+
546+
if node.keywords:
547+
raise TypeError("Function \"{0}\" does not support keyword "
548+
"arguments".format(res.name))
549+
550+
return res(*new_args, **kwargs)
551+
552+
else:
553+
554+
new_args = [ self.visit(arg).value for arg in node.args ]
555+
556+
for key in node.keywords:
557+
if not isinstance(key, ast.keyword):
558+
raise ValueError("keyword error in function call "
559+
"'{0}'".format(node.func.id))
560+
561+
if key.arg:
562+
kwargs.append(ast.keyword(keyword.arg, self.visit(keyword.value)))
563+
564+
return self.const_type(res(*new_args, **kwargs), self.env)
565+
566+
def visit_Call_legacy(self, node, side=None, **kwargs):
520567

521568
# this can happen with: datetime.datetime
522569
if isinstance(node.func, ast.Attribute):
@@ -607,6 +654,13 @@ def visitor(x, y):
607654
operands = node.values
608655
return reduce(visitor, operands)
609656

657+
# ast.Call signature changed on 3.5,
658+
# conditionally change which methods is named
659+
# visit_Call depending on Python version, #11097
660+
if compat.PY35:
661+
BaseExprVisitor.visit_Call = BaseExprVisitor.visit_Call_35
662+
else:
663+
BaseExprVisitor.visit_Call = BaseExprVisitor.visit_Call_legacy
610664

611665
_python_not_supported = frozenset(['Dict', 'BoolOp', 'In', 'NotIn'])
612666
_numexpr_supported_calls = frozenset(_reductions + _mathops)

pandas/io/tests/__init__.py

-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +0,0 @@
1-
2-
def setUp():
3-
import socket
4-
socket.setdefaulttimeout(5)

pandas/io/tests/test_data.py

+8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ def _skip_if_no_lxml():
2727
except ImportError:
2828
raise nose.SkipTest("no lxml")
2929

30+
def _skip_if_no_bs():
31+
try:
32+
import bs4
33+
import html5lib
34+
except ImportError:
35+
raise nose.SkipTest("no html5lib/bs4")
36+
3037

3138
def assert_n_failed_equals_n_null_columns(wngs, obj, cls=SymbolWarning):
3239
all_nan_cols = pd.Series(dict((k, pd.isnull(v).all()) for k, v in
@@ -288,6 +295,7 @@ class TestYahooOptions(tm.TestCase):
288295
def setUpClass(cls):
289296
super(TestYahooOptions, cls).setUpClass()
290297
_skip_if_no_lxml()
298+
_skip_if_no_bs()
291299

292300
# aapl has monthlies
293301
cls.aapl = web.Options('aapl', 'yahoo')

pandas/io/tests/test_pytables.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -2573,7 +2573,9 @@ def test_tuple_index(self):
25732573
idx = [(0., 1.), (2., 3.), (4., 5.)]
25742574
data = np.random.randn(30).reshape((3, 10))
25752575
DF = DataFrame(data, index=idx, columns=col)
2576-
with tm.assert_produces_warning(expected_warning=PerformanceWarning):
2576+
2577+
expected_warning = Warning if compat.PY35 else PerformanceWarning
2578+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
25772579
self._check_roundtrip(DF, tm.assert_frame_equal)
25782580

25792581
def test_index_types(self):
@@ -2585,23 +2587,25 @@ def test_index_types(self):
25852587
check_index_type=True,
25862588
check_series_type=True)
25872589

2588-
with tm.assert_produces_warning(expected_warning=PerformanceWarning):
2590+
# nose has a deprecation warning in 3.5
2591+
expected_warning = Warning if compat.PY35 else PerformanceWarning
2592+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
25892593
ser = Series(values, [0, 'y'])
25902594
self._check_roundtrip(ser, func)
25912595

2592-
with tm.assert_produces_warning(expected_warning=PerformanceWarning):
2596+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
25932597
ser = Series(values, [datetime.datetime.today(), 0])
25942598
self._check_roundtrip(ser, func)
25952599

2596-
with tm.assert_produces_warning(expected_warning=PerformanceWarning):
2600+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
25972601
ser = Series(values, ['y', 0])
25982602
self._check_roundtrip(ser, func)
25992603

2600-
with tm.assert_produces_warning(expected_warning=PerformanceWarning):
2604+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
26012605
ser = Series(values, [datetime.date.today(), 'a'])
26022606
self._check_roundtrip(ser, func)
26032607

2604-
with tm.assert_produces_warning(expected_warning=PerformanceWarning):
2608+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
26052609
ser = Series(values, [1.23, 'b'])
26062610
self._check_roundtrip(ser, func)
26072611

@@ -3377,7 +3381,8 @@ def test_retain_index_attributes2(self):
33773381

33783382
with ensure_clean_path(self.path) as path:
33793383

3380-
with tm.assert_produces_warning(expected_warning=AttributeConflictWarning):
3384+
expected_warning = Warning if compat.PY35 else AttributeConflictWarning
3385+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
33813386

33823387
df = DataFrame(dict(A = Series(lrange(3), index=date_range('2000-1-1',periods=3,freq='H'))))
33833388
df.to_hdf(path,'data',mode='w',append=True)
@@ -3391,7 +3396,7 @@ def test_retain_index_attributes2(self):
33913396

33923397
self.assertEqual(read_hdf(path,'data').index.name, 'foo')
33933398

3394-
with tm.assert_produces_warning(expected_warning=AttributeConflictWarning):
3399+
with tm.assert_produces_warning(expected_warning=expected_warning, check_stacklevel=False):
33953400

33963401
idx2 = date_range('2001-1-1',periods=3,freq='H')
33973402
idx2.name = 'bar'

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ def build_extensions(self):
181181
'Programming Language :: Python :: 2.7',
182182
'Programming Language :: Python :: 3.3',
183183
'Programming Language :: Python :: 3.4',
184+
'Programming Language :: Python :: 3.5',
184185
'Programming Language :: Cython',
185186
'Topic :: Scientific/Engineering',
186187
]

0 commit comments

Comments
 (0)