-
-
Notifications
You must be signed in to change notification settings - Fork 18.1k
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
DEPR: Deprecate Series.to_csv signature #21896
DEPR: Deprecate Series.to_csv signature #21896
Conversation
Hello @toobaz! Thanks for updating the PR. Cheers ! There are no PEP8 issues in this Pull Request. 🍻 Comment last updated on August 02, 2018 at 20:52 Hours UTC |
1fa5123
to
5175907
Compare
This is the solution that feels the most "just get it done" to me, while not breaking any "correctly written" code (as far as I can tell...?). |
pandas/core/generic.py
Outdated
European data | ||
|
||
""" | ||
|
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.
I think a few lines from the pull request of @gfyoung are missing here, something like
from pandas.core.frame import DataFrame
df = self if isinstance(self, DataFrame) else DataFrame(self)
If I am not mistaken, the purpose of those lines is to prepare for this method to be called by Series
.
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.
(added)
pandas/core/generic.py
Outdated
tupleize_cols = False | ||
|
||
from pandas.io.formats.csvs import CSVFormatter | ||
formatter = CSVFormatter(self, path_or_buf, |
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.
If you agree with to comment above, self
should be replaced by df
here.
Do you have in mind "uncorrectly written" code it could break? (EDIT: OK: if you mean "code which does not raise errors", I understand) |
Just the example of passing (EDIT: Precisely that) |
5175907
to
7d655b2
Compare
Codecov Report
@@ Coverage Diff @@
## master #21896 +/- ##
==========================================
- Coverage 92.06% 92.05% -0.01%
==========================================
Files 169 169
Lines 50694 50709 +15
==========================================
+ Hits 46671 46681 +10
- Misses 4023 4028 +5
Continue to review full report at Codecov.
|
Right, the previous version was wrong and incomplete. Should be fixed now, thanks. In [2]: s = pd.Series(list('abcd'))
In [3]: s.to_csv('/tmp/test1.csv', 'y')
/home/nobackup/repo/pandas/pandas/core/series.py:3812: UserWarning: Argument 'header' has changed default value to True: please pass an explicit value to suppress this warning
warnings.warn("Argument 'header' has changed default value to "
In [4]: cat /tmp/test1.csv
y0
0ya
1yb
2yc
3yd
In [5]: s.to_csv('/tmp/test1.csv', True)
/usr/bin/ipython3:1: FutureWarning: The signature of `Series.to_csv` was aligned to that of `DataFrame.to_csv`. Note that the order of arguments changed, and the new one has 'sep' in first place, for which "True" is not a valid value. The old order will cease to be supported in a future version. Please refer to the documentation for `DataFrame.to_csv` when updating your function calls.
#! /bin/sh
/home/nobackup/repo/pandas/pandas/core/series.py:3812: UserWarning: Argument 'header' has changed default value to True: please pass an explicit value to suppress this warning
warnings.warn("Argument 'header' has changed default value to "
In [6]: cat /tmp/test1.csv
,0
0,a
1,b
2,c
3,d |
7d655b2
to
446cd2c
Compare
Yes; one additional important change is that this PR tries to support both the old and the new positional signature (where "tries" means that it will never know for sure if some user had the idea to pass |
@jreback @jorisvandenbossche : Another friendly ping on this. |
I like this version. I think bending over to give a helpful error message is pretty useful to the user. This is not completely crazy and doesn't add a huge amount of code. I think a couple of TODO's were left in the code. |
a17429b
to
7c5e18d
Compare
@toobaz : Don't forget |
Tests are missing too, but I tought that maybe the simplest thing would be for you to take my code in your PR. Otherwise I can do the opposite (not sure when I'll find the time though). |
@toobaz : I can push to those changes to you branch. You have the changes, but just need the finishing touches, which I can add here. |
Sure, feel free (I saw now only that you closed the other one) |
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.
Only looking at this PR (I didn't follow all the other discussions), this looks good to me
pandas/core/series.py
Outdated
|
||
# This entire method is going to be removed, so the shared docstring | ||
# mechanism is overkill | ||
to_csv.__doc__ = generic.NDFrame.to_csv.__doc__ |
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.
This is not safe for builds without docstrings I think?
I also don't understand why using the shared docstring mechanism is overkill here? (it can simply be used to add a docstring from somewhere else, you can use without substituting values or so) Using that will simply be a one-line as well.
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.
This is not safe for builds without docstrings I think?
Didn't know about those (link?) In general if func
has no docstring, func.__doc__
is just None
... but again, I might be missing something.
Using that will simply be a one-line as well.
Wouldn't that mean changing pandas/core/generic.py
to insert the docstring inside _shared_docs
(and undo after deprecation)?
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.
Yeah, forget about the comment about builds without docstring, I always forget the exact semantics: they don't remove the attribute, just set it to None. So it is things like to_csv.__doc__ = generic.NDFrame.to_csv.__doc__ + "appending"
that then does not work.
Anyhow, you can do a
@Appender(generic.NDFrame.to_csv.__doc__)
which will do the same but with our machinery (and then you don't need the comment, 2 lines saved :-))
pandas/core/series.py
Outdated
if kwargs.get("header", None) is None: | ||
warnings.warn("The signature of `Series.to_csv` was aligned " | ||
"to that of `DataFrame.to_csv`, and argument " | ||
"'header' will change its default value to " |
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.
"change its default value to True" -> "change its default value from False to True" ?
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.
Did you test all cases of the deprecation warnings? (maybe I missed some, but I don't see any tests for the positional args case)
if arg == "path": | ||
kwargs = dict(path=path, header=False) | ||
elif arg == "header": | ||
kwargs = dict(path_or_buf=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.
Why would this case raise the warning? (as path_or_buf
is the future keyword?)
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.
Because header
will default to True
in the future (instead of False
as it was the case in Series.to_csv
). Thus, users who don't specify the header
argument will be "surprised" when that change in the default results in different output.
Thus, we are warning when header
is not passed in explicitly to let them know that the default is changing.
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.
ah, yes, missed that one
pandas/tests/test_common.py
Outdated
compressed = os.path.getsize(filename) | ||
getattr(obj, method)(filename, compression=None) | ||
uncompressed = os.path.getsize(filename) | ||
assert uncompressed > compressed |
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.
why would those cases raise any warnings?
(and same for the others below)
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.
Same answer as 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.
@toobaz can you add a comment explaining that? EDIT: I see now you already did :-)
doc/source/whatsnew/v0.24.0.txt
Outdated
@@ -383,6 +383,7 @@ Deprecations | |||
- :meth:`MultiIndex.to_hierarchical` is deprecated and will be removed in a future version (:issue:`21613`) | |||
- :meth:`Series.ptp` is deprecated. Use ``numpy.ptp`` instead (:issue:`21614`) | |||
- :meth:`Series.compress` is deprecated. Use ``Series[condition]`` instead (:issue:`18262`) | |||
- The signature in :meth:`Series.to_csv` has been deprecated. Please follow the signature in :meth:`DataFrame.to_csv` instead (:issue:`19715`) |
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.
I would give a bit more details here (or at least mention the most important ones: change in name of first argument + second positional argument is different, amongst other order changes)
pandas/core/series.py
Outdated
if path is None: | ||
return result | ||
def to_csv(self, *args, **kwargs): | ||
warning_klass = FutureWarning |
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 I don't understand the need for this variable (and the following)
pandas/core/series.py
Outdated
@Appender(generic.NDFrame.to_csv.__doc__) | ||
def to_csv(self, *args, **kwargs): | ||
warning_klass = FutureWarning | ||
stack_level = 2 |
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 I don't understand why we need those variables - they don't save code (actually the opposite) nor increase readability.
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.
agreed, I think you can just change this
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.
We use those variables in multiple places in this method to issue warnings about keyword arguments and the general deprecations. If you want to change this to copy and paste it everywhere, go ahead.
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.
If you want to change this to copy and paste it everywhere, go ahead.
It's actually how it was, but OK, I will :-)
24fd90f
to
e81e147
Compare
e81e147
to
e69c5ca
Compare
Rebased (on #22011 ) and added missing
|
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!
Thanks! |
git diff upstream/master -u -- "*.py" | flake8 --diff
Just a proof of concept for discussion (misses docs, whatsnew, new tests). Based on #21868@dahlbaek @gfyoung