-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Fix unbound local with bad engine #16511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix unbound local with bad engine #16511
Conversation
(or if you want to do this a totally different way / different error I can make changes or close) |
18c3012
to
6ba36e7
Compare
doc/source/whatsnew/v0.21.0.txt
Outdated
@@ -83,6 +83,8 @@ Performance Improvements | |||
Bug Fixes | |||
~~~~~~~~~ | |||
|
|||
- Passing an invalid engine to `read_csv` now raises an informative ValueError rather than UnboundLocalError. (:issue:`16511`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:func:read_csv
is better, double back-ticks on ValueError
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
u can put in0.20.2
@@ -99,3 +102,14 @@ def read_table(self, *args, **kwds): | |||
kwds = kwds.copy() | |||
kwds['engine'] = self.engine | |||
return read_table(*args, **kwds) | |||
|
|||
|
|||
class TestParameterValidation(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use tm.ensure_clean() as path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this test into common.py
(in same directory). This base test class should not be touched for organizational purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, why are we writing a round trip test? This can be much simpler:
data = "a\n1"
msg = "Unknown engine"
with tm.assert_raises_regex(ValueError, msg):
read_csv(StringIO(data), engine='pyt') # don't use self.read_csv because that will override the engine parameter
Oh and yes, use tm.assert_raises_regex
instead of the pytest.raises(...)
(pandas
regex error message matching is a little more compact).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docstring for tm.assert_raises_regex
says to use pytest.raises
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so okay that this will get run once for every engine, even though it's the same test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes! You're right. We changed our minds about that. Mind fixing the documentation on that in a separate commit / PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so okay that this will get run once for every engine, even though it's the same test?
Actually, better idea: move it to test_common.py
(the directory above)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm. minor comments.
def test_unknown_engine(self): | ||
with tempfile.NamedTemporaryFile() as fp: | ||
df = tm.makeDataFrame() | ||
df.to_csv(fp.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gfyoung good location for this type of test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. There shouldn't be any tests in this file. I made a comment here about it.
6ba36e7
to
26a3300
Compare
made all the requested changes - thanks for the review @jreback ! |
Codecov Report
@@ Coverage Diff @@
## master #16511 +/- ##
==========================================
- Coverage 90.79% 90.43% -0.37%
==========================================
Files 161 161
Lines 51063 51046 -17
==========================================
- Hits 46363 46162 -201
- Misses 4700 4884 +184
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #16511 +/- ##
==========================================
+ Coverage 90.79% 90.79% +<.01%
==========================================
Files 161 161
Lines 51063 51064 +1
==========================================
+ Hits 46363 46366 +3
+ Misses 4700 4698 -2
Continue to review full report at Codecov.
|
Previously had an UnboundLocalError - no fun!
26a3300
to
9a4f1a7
Compare
pandas/io/parsers.py
Outdated
@@ -969,6 +969,9 @@ def _make_engine(self, engine='c'): | |||
klass = PythonParser | |||
elif engine == 'python-fwf': | |||
klass = FixedWidthFieldParser | |||
else: | |||
raise ValueError('Unknown engine: %r (valid are "c", "python",' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about valid options are...
instead of valid are...
@jtratner : Thanks for this! Seems like we need some more fuzzy-testing for One minor comment about the actual error message, and two bigger ones regarding the actual test. |
doc/source/whatsnew/v0.20.2.txt
Outdated
@@ -39,6 +39,9 @@ Bug Fixes | |||
|
|||
- Bug in using ``pathlib.Path`` or ``py.path.local`` objects with io functions (:issue:`16291`) | |||
- Bug in ``DataFrame.update()`` with ``overwrite=False`` and ``NaN values`` (:issue:`15593`) | |||
- Passing an invalid engine to :func:`read_csv` now raises an informative | |||
ValueError rather than UnboundLocalError. (:issue:`16511`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double backtics on ValueError
and UnboundLocalError
pandas/io/parsers.py
Outdated
@@ -969,6 +969,9 @@ def _make_engine(self, engine='c'): | |||
klass = PythonParser | |||
elif engine == 'python-fwf': | |||
klass = FixedWidthFieldParser | |||
else: | |||
raise ValueError('Unknown engine: %r (valid are "c", "python",' | |||
' or "python-fwf")' % engine) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you use .format(...)
okay, covered everybody's comments and moved tests again |
@jtratner : LGTM! |
thanks! |
(cherry picked from commit 9b0ea41)
(cherry picked from commit 9b0ea41)
This was so small I figured simpler to put up a PR rather than issue then PR. :)
Previously, passing a bad engine to read_csv gave an less-than-informative UnboundLocalError:
Now it gives a much nicer ValueError:
git diff upstream/master --name-only -- '*.py' | flake8 --diff
I was not sure where to stick the test or the whatsnew entry (or if a whatsnew entry is really necessary), so please tell me if I should move it elsewhere.
Cheers!