Skip to content

Commit 6f1ade1

Browse files
committed
TST: remove ResourceWarnings from stat by auto-closing iterator
TST: install scipy wheels from master on 3.5/dev, xref #12887 TST: skip writing excel if no writers installed
1 parent 2ba977a commit 6f1ade1

File tree

10 files changed

+73
-37
lines changed

10 files changed

+73
-37
lines changed

ci/install-3.5_NUMPY_DEV.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ pip uninstall numpy -y
1515
time sudo apt-get $APT_ARGS install libatlas-base-dev gfortran
1616

1717
# install numpy wheel from master
18-
pip install --pre --upgrade --no-index --timeout=60 --trusted-host travis-dev-wheels.scipy.org -f http://travis-dev-wheels.scipy.org/ numpy
18+
pip install --pre --upgrade --no-index --timeout=60 --trusted-host travis-dev-wheels.scipy.org -f http://travis-dev-wheels.scipy.org/ numpy scipy
1919

2020
true

pandas/compat/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ def set_function_name(f, name, cls):
251251
f.__module__ = cls.__module__
252252
return f
253253

254+
ResourceWarning = ResourceWarning
255+
254256
else:
255257
string_types = basestring,
256258
integer_types = (int, long)
@@ -298,6 +300,8 @@ def set_function_name(f, name, cls):
298300
f.__name__ = name
299301
return f
300302

303+
class ResourceWarning(Warning): pass
304+
301305
string_and_binary_types = string_types + (binary_type,)
302306

303307

pandas/io/common.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ def _get_handle(path, mode, encoding=None, compression=None):
428428
return f
429429

430430

431-
class UTF8Recoder:
431+
class UTF8Recoder(BaseIterator):
432432

433433
"""
434434
Iterator that reads an encoded stream and reencodes the input to UTF-8
@@ -437,9 +437,6 @@ class UTF8Recoder:
437437
def __init__(self, f, encoding):
438438
self.reader = codecs.getreader(encoding)(f)
439439

440-
def __iter__(self):
441-
return self
442-
443440
def read(self, bytes=-1):
444441
return self.reader.read(bytes).encode("utf-8")
445442

@@ -449,9 +446,6 @@ def readline(self):
449446
def next(self):
450447
return next(self.reader).encode("utf-8")
451448

452-
# Python 3 iterator
453-
__next__ = next
454-
455449

456450
if compat.PY3: # pragma: no cover
457451
def UnicodeReader(f, dialect=csv.excel, encoding="utf-8", **kwds):

pandas/io/parsers.py

+9
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,12 @@ def __init__(self, f, engine=None, **kwds):
623623

624624
self._make_engine(self.engine)
625625

626+
def close(self):
627+
try:
628+
self._engine._reader.close()
629+
except:
630+
pass
631+
626632
def _get_options_with_defaults(self, engine):
627633
kwds = self.orig_options
628634

@@ -875,6 +881,9 @@ def __init__(self, kwds):
875881

876882
self._first_chunk = True
877883

884+
def close(self):
885+
self._reader.close()
886+
878887
@property
879888
def _has_complex_date_col(self):
880889
return (isinstance(self.parse_dates, dict) or

pandas/io/stata.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,15 @@ def read_stata(filepath_or_buffer, convert_dates=True,
161161
chunksize=chunksize, encoding=encoding)
162162

163163
if iterator or chunksize:
164-
return reader
165-
166-
return reader.read()
164+
try:
165+
return reader
166+
except StopIteration:
167+
reader.close()
168+
169+
try:
170+
return reader.read()
171+
finally:
172+
reader.close()
167173

168174
_date_formats = ["%tc", "%tC", "%td", "%d", "%tw", "%tm", "%tq", "%th", "%ty"]
169175

pandas/io/tests/test_excel.py

+3
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ def test_read_one_empty_col_no_header(self):
429429
tm.assert_frame_equal(actual_header_zero, expected)
430430

431431
def test_read_one_empty_col_with_header(self):
432+
_skip_if_no_xlwt()
433+
_skip_if_no_openpyxl()
434+
432435
df = pd.DataFrame(
433436
[["", 1, 100],
434437
["", 2, 200],

pandas/io/tests/test_parsers.py

+1
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,7 @@ def test_utf16_bom_skiprows(self):
20712071
sep=sep)
20722072
expected = self.read_csv(s, encoding='utf-8', skiprows=2,
20732073
sep=sep)
2074+
s.close()
20742075

20752076
tm.assert_frame_equal(result, expected)
20762077

pandas/io/tests/test_stata.py

+23-21
Original file line numberDiff line numberDiff line change
@@ -1024,28 +1024,29 @@ def test_read_chunks_117(self):
10241024
check_datetimelike_compat=True)
10251025

10261026
pos += chunksize
1027+
itr.close()
10271028

10281029
def test_iterator(self):
10291030

10301031
fname = self.dta3_117
10311032

10321033
parsed = read_stata(fname)
10331034

1034-
itr = read_stata(fname, iterator=True)
1035-
chunk = itr.read(5)
1036-
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk)
1035+
with read_stata(fname, iterator=True) as itr:
1036+
chunk = itr.read(5)
1037+
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk)
10371038

1038-
itr = read_stata(fname, chunksize=5)
1039-
chunk = list(itr)
1040-
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk[0])
1039+
with read_stata(fname, chunksize=5) as itr:
1040+
chunk = list(itr)
1041+
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk[0])
10411042

1042-
itr = read_stata(fname, iterator=True)
1043-
chunk = itr.get_chunk(5)
1044-
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk)
1043+
with read_stata(fname, iterator=True) as itr:
1044+
chunk = itr.get_chunk(5)
1045+
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk)
10451046

1046-
itr = read_stata(fname, chunksize=5)
1047-
chunk = itr.get_chunk()
1048-
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk)
1047+
with read_stata(fname, chunksize=5) as itr:
1048+
chunk = itr.get_chunk()
1049+
tm.assert_frame_equal(parsed.iloc[0:5, :], chunk)
10491050

10501051
# GH12153
10511052
from_chunks = pd.concat(read_stata(fname, chunksize=4))
@@ -1089,22 +1090,23 @@ def test_read_chunks_115(self):
10891090
check_datetimelike_compat=True)
10901091

10911092
pos += chunksize
1093+
itr.close()
10921094

10931095
def test_read_chunks_columns(self):
10941096
fname = self.dta3_117
10951097
columns = ['quarter', 'cpi', 'm1']
10961098
chunksize = 2
10971099

10981100
parsed = read_stata(fname, columns=columns)
1099-
itr = read_stata(fname, iterator=True)
1100-
pos = 0
1101-
for j in range(5):
1102-
chunk = itr.read(chunksize, columns=columns)
1103-
if chunk is None:
1104-
break
1105-
from_frame = parsed.iloc[pos:pos + chunksize, :]
1106-
tm.assert_frame_equal(from_frame, chunk, check_dtype=False)
1107-
pos += chunksize
1101+
with read_stata(fname, iterator=True) as itr:
1102+
pos = 0
1103+
for j in range(5):
1104+
chunk = itr.read(chunksize, columns=columns)
1105+
if chunk is None:
1106+
break
1107+
from_frame = parsed.iloc[pos:pos + chunksize, :]
1108+
tm.assert_frame_equal(from_frame, chunk, check_dtype=False)
1109+
pos += chunksize
11081110

11091111

11101112
if __name__ == '__main__':

pandas/parser.pyx

+12
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ cdef class TextReader:
258258
parser_t *parser
259259
object file_handle, na_fvalues
260260
object true_values, false_values
261+
object dsource
261262
bint na_filter, verbose, has_usecols, has_mi_columns
262263
int parser_start
263264
list clocks
@@ -535,6 +536,15 @@ cdef class TextReader:
535536
kh_destroy_str(self.true_set)
536537
kh_destroy_str(self.false_set)
537538

539+
def close(self):
540+
# we need to properly close an open derived
541+
# filehandle here, e.g. and UTFRecoder
542+
if self.dsource is not None:
543+
try:
544+
self.dsource.close()
545+
except:
546+
pass
547+
538548
def set_error_bad_lines(self, int status):
539549
self.parser.error_bad_lines = status
540550

@@ -635,6 +645,8 @@ cdef class TextReader:
635645
raise IOError('Expected file path name or file-like object,'
636646
' got %s type' % type(source))
637647

648+
self.dsource = source
649+
638650
cdef _get_header(self):
639651
# header is now a list of lists, so field_count should use header[0]
640652

pandas/util/testing.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
import pandas.lib as lib
3434
from pandas.compat import(
3535
filter, map, zip, range, unichr, lrange, lmap, lzip, u, callable, Counter,
36-
raise_with_traceback, httplib, is_platform_windows, is_platform_32bit
36+
raise_with_traceback, httplib, is_platform_windows, is_platform_32bit,
37+
PY3
3738
)
3839

3940
from pandas.computation import expressions as expr
@@ -51,18 +52,22 @@
5152

5253

5354
# set testing_mode
55+
_testing_mode_warnings = (DeprecationWarning, compat.ResourceWarning)
56+
57+
5458
def set_testing_mode():
5559
# set the testing mode filters
5660
testing_mode = os.environ.get('PANDAS_TESTING_MODE', 'None')
5761
if 'deprecate' in testing_mode:
58-
warnings.simplefilter('always', DeprecationWarning)
62+
63+
warnings.simplefilter('always', _testing_mode_warnings)
5964

6065

6166
def reset_testing_mode():
6267
# reset the testing mode filters
6368
testing_mode = os.environ.get('PANDAS_TESTING_MODE', 'None')
6469
if 'deprecate' in testing_mode:
65-
warnings.simplefilter('ignore', DeprecationWarning)
70+
warnings.simplefilter('ignore', _testing_mode_warnings)
6671

6772
set_testing_mode()
6873

@@ -286,7 +291,7 @@ def _skip_if_no_dateutil():
286291

287292

288293
def _skip_if_windows_python_3():
289-
if compat.PY3 and is_platform_windows():
294+
if PY3 and is_platform_windows():
290295
import nose
291296
raise nose.SkipTest("not used on python 3/win32")
292297

@@ -437,7 +442,7 @@ def get_locales(prefix=None, normalize=True,
437442
raw_locales = raw_locales.split(b'\n')
438443
out_locales = []
439444
for x in raw_locales:
440-
if compat.PY3:
445+
if PY3:
441446
out_locales.append(str(
442447
x, encoding=pd.options.display.encoding))
443448
else:

0 commit comments

Comments
 (0)