Skip to content

Commit aa88215

Browse files
gfyoungjreback
authored andcommitted
API: Deprecate skip_footer in read_csv
Title is self-explanatory. Closes gh-13349 and partially undoes this <a href="9ceea2fd46e79f37 269a32de8c140cddf90eda13">commit</a> back in `v0.9.0`. With such a massive API now, having duplicate arguments makes managing it way less practical. Author: gfyoung <gfyoung17@gmail.com> Closes #13386 from gfyoung/deprecate-dup-skipfooter and squashes the following commits: d21345f [gfyoung] API: Deprecate skip_footer in read_csv
1 parent e908733 commit aa88215

File tree

8 files changed

+54
-41
lines changed

8 files changed

+54
-41
lines changed

Diff for: doc/source/io.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ skiprows : list-like or integer, default ``None``
175175
of the file.
176176
skipfooter : int, default ``0``
177177
Number of lines at bottom of file to skip (unsupported with engine='c').
178+
skip_footer : int, default ``0``
179+
DEPRECATED: use the ``skipfooter`` parameter instead, as they are identical
178180
nrows : int, default ``None``
179181
Number of rows of file to read. Useful for reading pieces of large files.
180182
low_memory : boolean, default ``True``
@@ -1411,7 +1413,7 @@ back to python if C-unsupported options are specified. Currently, C-unsupported
14111413
options include:
14121414

14131415
- ``sep`` other than a single character (e.g. regex separators)
1414-
- ``skip_footer``
1416+
- ``skipfooter``
14151417
- ``sep=None`` with ``delim_whitespace=False``
14161418

14171419
Specifying any of the above options will produce a ``ParserWarning`` unless the

Diff for: doc/source/whatsnew/v0.19.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ Deprecations
671671
- ``compact_ints`` and ``use_unsigned`` have been deprecated in ``pd.read_csv()`` and will be removed in a future version (:issue:`13320`)
672672
- ``buffer_lines`` has been deprecated in ``pd.read_csv()`` and will be removed in a future version (:issue:`13360`)
673673
- ``as_recarray`` has been deprecated in ``pd.read_csv()`` and will be removed in a future version (:issue:`13373`)
674+
- ``skip_footer`` has been deprecated in ``pd.read_csv()`` in favor of ``skipfooter`` and will be removed in a future version (:issue:`13349`)
674675
- top-level ``pd.ordered_merge()`` has been renamed to ``pd.merge_ordered()`` and the original name will be removed in a future version (:issue:`13358`)
675676
- ``Timestamp.offset`` property (and named arg in the constructor), has been deprecated in favor of ``freq`` (:issue:`12160`)
676677
- ``pd.tseries.util.pivot_annual`` is deprecated. Use ``pivot_table`` as alternative, an example is :ref:`here <cookbook.pivot>` (:issue:`736`)

Diff for: pandas/io/excel.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ def _parse_cell(cell_contents, cell_typ):
473473
parse_dates=parse_dates,
474474
date_parser=date_parser,
475475
skiprows=skiprows,
476-
skip_footer=skip_footer,
476+
skipfooter=skip_footer,
477477
squeeze=squeeze,
478478
**kwds)
479479

Diff for: pandas/io/parsers.py

+24-19
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@
125125
at the start of the file
126126
skipfooter : int, default 0
127127
Number of lines at bottom of file to skip (Unsupported with engine='c')
128+
skip_footer : int, default 0
129+
DEPRECATED: use the `skipfooter` parameter instead, as they are identical
128130
nrows : int, default None
129131
Number of rows of file to read. Useful for reading pieces of large files
130132
na_values : str or list-like or dict, default None
@@ -341,9 +343,6 @@ def _validate_nrows(nrows):
341343
def _read(filepath_or_buffer, kwds):
342344
"Generic reader of line files."
343345
encoding = kwds.get('encoding', None)
344-
skipfooter = kwds.pop('skipfooter', None)
345-
if skipfooter is not None:
346-
kwds['skip_footer'] = skipfooter
347346

348347
# If the input could be a filename, check for a recognizable compression
349348
# extension. If we're reading from a URL, the `get_filepath_or_buffer`
@@ -411,8 +410,8 @@ def _read(filepath_or_buffer, kwds):
411410
'na_values': None,
412411
'true_values': None,
413412
'false_values': None,
414-
'skip_footer': 0,
415413
'converters': None,
414+
'skipfooter': 0,
416415

417416
'keep_default_na': True,
418417
'thousands': None,
@@ -461,7 +460,7 @@ def _read(filepath_or_buffer, kwds):
461460
'widths': None,
462461
}
463462

464-
_c_unsupported = set(['skip_footer'])
463+
_c_unsupported = set(['skipfooter'])
465464
_python_unsupported = set([
466465
'low_memory',
467466
'buffer_lines',
@@ -503,7 +502,6 @@ def parser_f(filepath_or_buffer,
503502
false_values=None,
504503
skipinitialspace=False,
505504
skiprows=None,
506-
skipfooter=None,
507505
nrows=None,
508506

509507
# NA and Missing Data Handling
@@ -541,8 +539,8 @@ def parser_f(filepath_or_buffer,
541539
error_bad_lines=True,
542540
warn_bad_lines=True,
543541

544-
# Deprecated
545-
skip_footer=0,
542+
skipfooter=0,
543+
skip_footer=0, # deprecated
546544

547545
# Internal
548546
doublequote=True,
@@ -570,6 +568,13 @@ def parser_f(filepath_or_buffer,
570568
engine = 'c'
571569
engine_specified = False
572570

571+
if skip_footer != 0:
572+
warnings.warn("The 'skip_footer' argument has "
573+
"been deprecated and will be removed "
574+
"in a future version. Please use the "
575+
"'skipfooter' argument instead.",
576+
FutureWarning, stacklevel=2)
577+
573578
kwds = dict(delimiter=delimiter,
574579
engine=engine,
575580
dialect=dialect,
@@ -768,9 +773,9 @@ def _clean_options(self, options, engine):
768773

769774
# C engine not supported yet
770775
if engine == 'c':
771-
if options['skip_footer'] > 0:
776+
if options['skipfooter'] > 0:
772777
fallback_reason = "the 'c' engine does not support"\
773-
" skip_footer"
778+
" skipfooter"
774779
engine = 'python'
775780

776781
if sep is None and not delim_whitespace:
@@ -903,8 +908,8 @@ def _failover_to_python(self):
903908

904909
def read(self, nrows=None):
905910
if nrows is not None:
906-
if self.options.get('skip_footer'):
907-
raise ValueError('skip_footer not supported for iteration')
911+
if self.options.get('skipfooter'):
912+
raise ValueError('skipfooter not supported for iteration')
908913

909914
ret = self._engine.read(nrows)
910915

@@ -1591,7 +1596,7 @@ def TextParser(*args, **kwds):
15911596
date_parser : function, default None
15921597
skiprows : list of integers
15931598
Row numbers to skip
1594-
skip_footer : int
1599+
skipfooter : int
15951600
Number of line at bottom of file to skip
15961601
converters : dict, default None
15971602
Dict of functions for converting values in certain columns. Keys can
@@ -1704,7 +1709,7 @@ def __init__(self, f, **kwds):
17041709
self.memory_map = kwds['memory_map']
17051710
self.skiprows = kwds['skiprows']
17061711

1707-
self.skip_footer = kwds['skip_footer']
1712+
self.skipfooter = kwds['skipfooter']
17081713
self.delimiter = kwds['delimiter']
17091714

17101715
self.quotechar = kwds['quotechar']
@@ -2340,7 +2345,7 @@ def _rows_to_cols(self, content):
23402345
content, min_width=col_len).T)
23412346
zip_len = len(zipped_content)
23422347

2343-
if self.skip_footer < 0:
2348+
if self.skipfooter < 0:
23442349
raise ValueError('skip footer cannot be negative')
23452350

23462351
# Loop through rows to verify lengths are correct.
@@ -2353,8 +2358,8 @@ def _rows_to_cols(self, content):
23532358
break
23542359

23552360
footers = 0
2356-
if self.skip_footer:
2357-
footers = self.skip_footer
2361+
if self.skipfooter:
2362+
footers = self.skipfooter
23582363

23592364
row_num = self.pos - (len(content) - i + footers)
23602365

@@ -2440,8 +2445,8 @@ def _get_lines(self, rows=None):
24402445
else:
24412446
lines = new_rows
24422447

2443-
if self.skip_footer:
2444-
lines = lines[:-self.skip_footer]
2448+
if self.skipfooter:
2449+
lines = lines[:-self.skipfooter]
24452450

24462451
lines = self._check_comments(lines)
24472452
if self.skip_blank_lines:

Diff for: pandas/io/tests/parser/common.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,9 @@ def test_malformed(self):
218218
skiprows=[2])
219219
it.read()
220220

221-
# skip_footer is not supported with the C parser yet
221+
# skipfooter is not supported with the C parser yet
222222
if self.engine == 'python':
223-
# skip_footer
223+
# skipfooter
224224
data = """ignore
225225
A,B,C
226226
1,2,3 # comment
@@ -232,7 +232,7 @@ def test_malformed(self):
232232
with tm.assertRaisesRegexp(Exception, msg):
233233
self.read_table(StringIO(data), sep=',',
234234
header=1, comment='#',
235-
skip_footer=1)
235+
skipfooter=1)
236236

237237
def test_quoting(self):
238238
bad_line_small = """printer\tresult\tvariant_name
@@ -536,11 +536,11 @@ def test_iterator(self):
536536
self.assertEqual(len(result), 3)
537537
tm.assert_frame_equal(pd.concat(result), expected)
538538

539-
# skip_footer is not supported with the C parser yet
539+
# skipfooter is not supported with the C parser yet
540540
if self.engine == 'python':
541-
# test bad parameter (skip_footer)
541+
# test bad parameter (skipfooter)
542542
reader = self.read_csv(StringIO(self.data1), index_col=0,
543-
iterator=True, skip_footer=True)
543+
iterator=True, skipfooter=True)
544544
self.assertRaises(ValueError, reader.read, 3)
545545

546546
def test_pass_names_with_index(self):

Diff for: pandas/io/tests/parser/python_parser_only.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def test_single_line(self):
9898
finally:
9999
sys.stdout = sys.__stdout__
100100

101-
def test_skip_footer(self):
101+
def test_skipfooter(self):
102102
# see gh-6607
103103
data = """A,B,C
104104
1,2,3
@@ -107,7 +107,7 @@ def test_skip_footer(self):
107107
want to skip this
108108
also also skip this
109109
"""
110-
result = self.read_csv(StringIO(data), skip_footer=2)
110+
result = self.read_csv(StringIO(data), skipfooter=2)
111111
no_footer = '\n'.join(data.split('\n')[:-3])
112112
expected = self.read_csv(StringIO(no_footer))
113113
tm.assert_frame_equal(result, expected)

Diff for: pandas/io/tests/parser/test_unsupported.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def test_c_engine(self):
5252
with tm.assertRaisesRegexp(ValueError, msg):
5353
read_table(StringIO(data), sep='\s', dtype={'a': float})
5454
with tm.assertRaisesRegexp(ValueError, msg):
55-
read_table(StringIO(data), skip_footer=1, dtype={'a': float})
55+
read_table(StringIO(data), skipfooter=1, dtype={'a': float})
5656

5757
# specify C engine with unsupported options (raise)
5858
with tm.assertRaisesRegexp(ValueError, msg):
@@ -61,15 +61,15 @@ def test_c_engine(self):
6161
with tm.assertRaisesRegexp(ValueError, msg):
6262
read_table(StringIO(data), engine='c', sep='\s')
6363
with tm.assertRaisesRegexp(ValueError, msg):
64-
read_table(StringIO(data), engine='c', skip_footer=1)
64+
read_table(StringIO(data), engine='c', skipfooter=1)
6565

6666
# specify C-unsupported options without python-unsupported options
6767
with tm.assert_produces_warning(parsers.ParserWarning):
6868
read_table(StringIO(data), sep=None, delim_whitespace=False)
6969
with tm.assert_produces_warning(parsers.ParserWarning):
7070
read_table(StringIO(data), sep='\s')
7171
with tm.assert_produces_warning(parsers.ParserWarning):
72-
read_table(StringIO(data), skip_footer=1)
72+
read_table(StringIO(data), skipfooter=1)
7373

7474
text = """ A B C D E
7575
one two three four
@@ -127,15 +127,20 @@ def test_deprecated_args(self):
127127
'as_recarray': True,
128128
'buffer_lines': True,
129129
'compact_ints': True,
130+
'skip_footer': True,
130131
'use_unsigned': True,
131132
}
132133

133134
engines = 'c', 'python'
134135

135136
for engine in engines:
136137
for arg, non_default_val in deprecated.items():
138+
if engine == 'c' and arg == 'skip_footer':
139+
# unsupported --> exception is raised
140+
continue
141+
137142
if engine == 'python' and arg == 'buffer_lines':
138-
# unsupported --> exception is raised first
143+
# unsupported --> exception is raised
139144
continue
140145

141146
with tm.assert_produces_warning(

Diff for: pandas/parser.pyx

+8-8
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ cdef extern from "parser/tokenizer.h":
165165

166166
void *skipset
167167
int64_t skip_first_N_rows
168-
int skip_footer
168+
int skipfooter
169169
double (*converter)(const char *, char **, char, char, char, int) nogil
170170

171171
# error handling
@@ -270,7 +270,7 @@ cdef class TextReader:
270270
kh_str_t *true_set
271271

272272
cdef public:
273-
int leading_cols, table_width, skip_footer, buffer_lines
273+
int leading_cols, table_width, skipfooter, buffer_lines
274274
object allow_leading_cols
275275
object delimiter, converters, delim_whitespace
276276
object na_values
@@ -338,7 +338,7 @@ cdef class TextReader:
338338
low_memory=False,
339339
buffer_lines=None,
340340
skiprows=None,
341-
skip_footer=0,
341+
skipfooter=0,
342342
verbose=False,
343343
mangle_dupe_cols=True,
344344
tupleize_cols=False,
@@ -418,15 +418,15 @@ cdef class TextReader:
418418
if skiprows is not None:
419419
self._make_skiprow_set()
420420

421-
self.skip_footer = skip_footer
421+
self.skipfooter = skipfooter
422422

423423
# suboptimal
424424
if usecols is not None:
425425
self.has_usecols = 1
426426
self.usecols = set(usecols)
427427

428428
# XXX
429-
if skip_footer > 0:
429+
if skipfooter > 0:
430430
self.parser.error_bad_lines = 0
431431
self.parser.warn_bad_lines = 0
432432

@@ -912,8 +912,8 @@ cdef class TextReader:
912912
if buffered_lines < irows:
913913
self._tokenize_rows(irows - buffered_lines)
914914

915-
if self.skip_footer > 0:
916-
raise ValueError('skip_footer can only be used to read '
915+
if self.skipfooter > 0:
916+
raise ValueError('skipfooter can only be used to read '
917917
'the whole file')
918918
else:
919919
with nogil:
@@ -926,7 +926,7 @@ cdef class TextReader:
926926

927927
if status < 0:
928928
raise_parser_error('Error tokenizing data', self.parser)
929-
footer = self.skip_footer
929+
footer = self.skipfooter
930930

931931
if self.parser_start == self.parser.lines:
932932
raise StopIteration

0 commit comments

Comments
 (0)