Skip to content

Commit fb24c0f

Browse files
committed
DEPR: Deprecate CParserError in favor of ParserError.
Partially resolves pandas-devgh-12665.
1 parent d7fb5bd commit fb24c0f

File tree

12 files changed

+45
-27
lines changed

12 files changed

+45
-27
lines changed

doc/source/io.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -1165,8 +1165,8 @@ too many will cause an error by default:
11651165
11661166
In [28]: pd.read_csv(StringIO(data))
11671167
---------------------------------------------------------------------------
1168-
CParserError Traceback (most recent call last)
1169-
CParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4
1168+
ParserError Traceback (most recent call last)
1169+
ParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4
11701170
11711171
You can elect to skip bad lines:
11721172

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Backwards incompatible API changes
4141
.. _whatsnew_0200.api:
4242

4343

44+
- ``CParserError`` has been deprecated in favor of ``ParserError`` in ``pd.read_csv`` (:issue:`12665`)
4445

4546

4647

pandas/io/common.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from pandas.formats.printing import pprint_thing
1414
from pandas.core.common import AbstractMethodError
1515
from pandas.types.common import is_number
16+
from pandas.util.decorators import deprecate
1617

1718
# common NA values
1819
# no longer excluding inf representations
@@ -65,13 +66,14 @@ def urlopen(*args, **kwargs):
6566
_VALID_URLS.discard('')
6667

6768

68-
class CParserError(ValueError):
69+
class ParserError(ValueError):
6970
"""
70-
Exception that is thrown by the C engine when it encounters
71-
a parsing error in `pd.read_csv`
71+
Exception that is thrown by an error is encountered in `pd.read_csv`
7272
"""
7373
pass
7474

75+
CParserError = deprecate('CParserError', ParserError, internal=True)
76+
7577

7678
class DtypeWarning(Warning):
7779
"""

pandas/io/parsers.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from pandas.io.date_converters import generic_parser
2727
from pandas.io.common import (get_filepath_or_buffer, _validate_header_arg,
2828
_get_handle, UnicodeReader, UTF8Recoder,
29-
BaseIterator, CParserError, EmptyDataError,
29+
BaseIterator, ParserError, EmptyDataError,
3030
ParserWarning, _NA_VALUES)
3131
from pandas.tseries import tools
3232

@@ -1141,7 +1141,7 @@ def tostr(x):
11411141
# long
11421142
for n in range(len(columns[0])):
11431143
if all(['Unnamed' in tostr(c[n]) for c in columns]):
1144-
raise CParserError(
1144+
raise ParserError(
11451145
"Passed header=[%s] are too many rows for this "
11461146
"multi_index of columns"
11471147
% ','.join([str(x) for x in self.header])

pandas/io/tests/parser/common.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def test_bad_stream_exception(self):
5050
# Issue 13652:
5151
# This test validates that both python engine
5252
# and C engine will raise UnicodeDecodeError instead of
53-
# c engine raising CParserError and swallowing exception
53+
# c engine raising ParserError and swallowing exception
5454
# that caused read to fail.
5555
handle = open(self.csv_shiftjs, "rb")
5656
codec = codecs.lookup("utf-8")

pandas/io/tests/parser/test_textreader.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def test_skip_bad_lines(self):
154154

155155
reader = TextReader(StringIO(data), delimiter=':',
156156
header=None)
157-
self.assertRaises(parser.CParserError, reader.read)
157+
self.assertRaises(parser.ParserError, reader.read)
158158

159159
reader = TextReader(StringIO(data), delimiter=':',
160160
header=None,
@@ -197,7 +197,7 @@ def test_header_not_enough_lines(self):
197197
assert_array_dicts_equal(expected, recs)
198198

199199
# not enough rows
200-
self.assertRaises(parser.CParserError, TextReader, StringIO(data),
200+
self.assertRaises(parser.ParserError, TextReader, StringIO(data),
201201
delimiter=',', header=5, as_recarray=True)
202202

203203
def test_header_not_enough_lines_as_recarray(self):
@@ -218,7 +218,7 @@ def test_header_not_enough_lines_as_recarray(self):
218218
assert_array_dicts_equal(expected, recs)
219219

220220
# not enough rows
221-
self.assertRaises(parser.CParserError, TextReader, StringIO(data),
221+
self.assertRaises(parser.ParserError, TextReader, StringIO(data),
222222
delimiter=',', header=5, as_recarray=True)
223223

224224
def test_escapechar(self):

pandas/io/tests/parser/test_unsupported.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import pandas.util.testing as tm
1616

1717
from pandas.compat import StringIO
18-
from pandas.io.common import CParserError
18+
from pandas.io.common import ParserError
1919
from pandas.io.parsers import read_csv, read_table
2020

2121

@@ -78,9 +78,9 @@ def test_c_engine(self):
7878
x q 30 3 -0.6662 -0.5243 -0.3580 0.89145 2.5838"""
7979
msg = 'Error tokenizing data'
8080

81-
with tm.assertRaisesRegexp(CParserError, msg):
81+
with tm.assertRaisesRegexp(ParserError, msg):
8282
read_table(StringIO(text), sep='\s+')
83-
with tm.assertRaisesRegexp(CParserError, msg):
83+
with tm.assertRaisesRegexp(ParserError, msg):
8484
read_table(StringIO(text), engine='c', sep='\s+')
8585

8686
msg = "Only length-1 thousands markers supported"

pandas/io/tests/test_common.py

+7
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,10 @@ def test_next(self):
139139
self.assertEqual(next_line.strip(), line.strip())
140140

141141
self.assertRaises(StopIteration, next, wrapper)
142+
143+
def test_cparser_error_depr(self):
144+
# see gh-12665
145+
with tm.assert_produces_warning(DeprecationWarning,
146+
check_stacklevel=False):
147+
with tm.assertRaises(common.ParserError):
148+
raise common.CParserError()

pandas/io/tests/test_html.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
is_platform_windows)
2424
from pandas.io.common import URLError, urlopen, file_path_to_url
2525
from pandas.io.html import read_html
26-
from pandas.parser import CParserError
26+
from pandas.parser import ParserError
2727

2828
import pandas.util.testing as tm
2929
from pandas.util.testing import makeCustomDataframe as mkdf, network
@@ -652,7 +652,7 @@ def test_parse_dates_combine(self):
652652

653653
def test_computer_sales_page(self):
654654
data = os.path.join(DATA_PATH, 'computer_sales_page.html')
655-
with tm.assertRaisesRegexp(CParserError, r"Passed header=\[0,1\] are "
655+
with tm.assertRaisesRegexp(ParserError, r"Passed header=\[0,1\] are "
656656
"too many rows for this multi_index "
657657
"of columns"):
658658
self.read_html(data, header=[0, 1])

pandas/parser.pyx

+10-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ from cpython cimport (PyObject, PyBytes_FromString,
1313
PyUnicode_Check, PyUnicode_AsUTF8String,
1414
PyErr_Occurred, PyErr_Fetch)
1515
from cpython.ref cimport PyObject, Py_XDECREF
16-
from io.common import CParserError, DtypeWarning, EmptyDataError
16+
# XXX: It's annoying that we have to import both CParserError
17+
# and ParserError. Unfortunately, backwards compatibility is
18+
# the higher calling right now.
19+
from io.common import CParserError, ParserError, DtypeWarning, EmptyDataError
1720

1821

1922
cdef extern from "Python.h":
@@ -720,7 +723,7 @@ cdef class TextReader:
720723
if isinstance(msg, list):
721724
msg = "[%s], len of %d," % (
722725
','.join([ str(m) for m in msg ]), len(msg))
723-
raise CParserError(
726+
raise ParserError(
724727
'Passed header=%s but only %d lines in file'
725728
% (msg, self.parser.lines))
726729

@@ -813,7 +816,7 @@ cdef class TextReader:
813816
passed_count = len(header[0])
814817

815818
# if passed_count > field_count:
816-
# raise CParserError('Column names have %d fields, '
819+
# raise ParserError('Column names have %d fields, '
817820
# 'data has %d fields'
818821
# % (passed_count, field_count))
819822

@@ -1005,7 +1008,7 @@ cdef class TextReader:
10051008
(num_cols >= self.parser.line_fields[i]) * num_cols
10061009

10071010
if self.table_width - self.leading_cols > num_cols:
1008-
raise CParserError(
1011+
raise ParserError(
10091012
"Too many columns specified: expected %s and found %s" %
10101013
(self.table_width - self.leading_cols, num_cols))
10111014

@@ -1060,7 +1063,7 @@ cdef class TextReader:
10601063
self.use_unsigned)
10611064

10621065
if col_res is None:
1063-
raise CParserError('Unable to parse column %d' % i)
1066+
raise ParserError('Unable to parse column %d' % i)
10641067

10651068
results[i] = col_res
10661069

@@ -1311,7 +1314,7 @@ def _is_file_like(obj):
13111314
if PY3:
13121315
import io
13131316
if isinstance(obj, io.TextIOWrapper):
1314-
raise CParserError('Cannot handle open unicode files (yet)')
1317+
raise ParserError('Cannot handle open unicode files (yet)')
13151318

13161319
# BufferedReader is a byte reader for Python 3
13171320
file = io.BufferedReader
@@ -2016,7 +2019,7 @@ cdef raise_parser_error(object base, parser_t *parser):
20162019
else:
20172020
message += 'no error message set'
20182021

2019-
raise CParserError(message)
2022+
raise ParserError(message)
20202023

20212024

20222025
def _concatenate_chunks(list chunks):

pandas/tests/frame/test_to_csv.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import numpy as np
99

1010
from pandas.compat import (lmap, range, lrange, StringIO, u)
11-
from pandas.parser import CParserError
11+
from pandas.parser import ParserError
1212
from pandas import (DataFrame, Index, Series, MultiIndex, Timestamp,
1313
date_range, read_csv, compat, to_datetime)
1414
import pandas as pd
@@ -589,7 +589,7 @@ def _make_frame(names=None):
589589

590590
for i in [5, 6, 7]:
591591
msg = 'len of {i}, but only 5 lines in file'.format(i=i)
592-
with assertRaisesRegexp(CParserError, msg):
592+
with assertRaisesRegexp(ParserError, msg):
593593
read_csv(path, tupleize_cols=False,
594594
header=lrange(i), index_col=0)
595595

pandas/util/decorators.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
from functools import wraps
77

88

9-
def deprecate(name, alternative, alt_name=None):
9+
def deprecate(name, alternative, alt_name=None, internal=False):
1010
alt_name = alt_name or alternative.__name__
1111

12+
# If we're deprecating something internally, use DeprecationWarning
13+
# so that we don't bother users with warnings out of their control.
14+
# For external things, use FutureWarning instead.
15+
_warning = DeprecationWarning if internal else FutureWarning
16+
1217
def wrapper(*args, **kwargs):
1318
warnings.warn("%s is deprecated. Use %s instead" % (name, alt_name),
14-
FutureWarning, stacklevel=2)
19+
_warning, stacklevel=2)
1520
return alternative(*args, **kwargs)
1621
return wrapper
1722

0 commit comments

Comments
 (0)