Skip to content

Make os.linesep default line_terminator in to_clipboard #13125

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1211,20 +1211,19 @@ def to_pickle(self, path):
from pandas.io.pickle import to_pickle
return to_pickle(self, path)

def to_clipboard(self, excel=None, sep=None, **kwargs):
def to_clipboard(self, excel=True, **kwargs):
"""
Attempt to write text representation of object to the system clipboard
This can be pasted into Excel, for example.

Parameters
----------
excel : boolean, defaults to True
if True, use the provided separator, writing in a csv
format for allowing easy pasting into excel.
if True, use '\\t' separator and os.linesep line terminator by
default, write to csv format to allow easy pasting into excel.
if False, write a string representation of the object
to the clipboard
sep : optional, defaults to tab
other keywords are passed to to_csv
other keywords are passed to to_csv or DataFrame.to_string

Notes
-----
Expand All @@ -1234,7 +1233,7 @@ def to_clipboard(self, excel=None, sep=None, **kwargs):
- OS X: none
"""
from pandas.io import clipboard
clipboard.to_clipboard(self, excel=excel, sep=sep, **kwargs)
clipboard.to_clipboard(self, excel=excel, **kwargs)

def to_xarray(self):
"""
Expand Down
7 changes: 5 additions & 2 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -2552,7 +2552,8 @@ def from_csv(cls, path, sep=',', parse_dates=True, header=None,

def to_csv(self, path=None, index=True, sep=",", na_rep='',
float_format=None, header=False, index_label=None,
mode='w', encoding=None, date_format=None, decimal='.'):
mode='w', encoding=None, date_format=None, decimal='.',
line_terminator='\n'):
"""
Write Series to a comma-separated values (csv) file

Expand Down Expand Up @@ -2584,6 +2585,8 @@ def to_csv(self, path=None, index=True, sep=",", na_rep='',
decimal: string, default '.'
Character recognized as decimal separator. E.g. use ',' for
European data
line_terminator : string, default '\\n'
The newline character or character sequence to use in the output file
"""
from pandas.core.frame import DataFrame
df = DataFrame(self)
Expand All @@ -2592,7 +2595,7 @@ def to_csv(self, path=None, index=True, sep=",", na_rep='',
float_format=float_format, header=header,
index_label=index_label, mode=mode,
encoding=encoding, date_format=date_format,
decimal=decimal)
decimal=decimal, line_terminator=line_terminator)
if path is None:
return result

Expand Down
40 changes: 20 additions & 20 deletions pandas/io/clipboard.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
""" io on the clipboard """
from pandas import compat, get_option, option_context, DataFrame
from pandas import compat, get_option, option_context, DataFrame, Series
from pandas.compat import StringIO


Expand Down Expand Up @@ -51,7 +51,7 @@ def read_clipboard(**kwargs): # pragma: no cover
return read_table(StringIO(text), **kwargs)


def to_clipboard(obj, excel=None, sep=None, **kwargs): # pragma: no cover
def to_clipboard(obj, excel=True, **kwargs): # pragma: no cover
"""
Attempt to write text representation of object to the system clipboard
The clipboard can be then pasted into Excel for example.
Expand All @@ -60,12 +60,11 @@ def to_clipboard(obj, excel=None, sep=None, **kwargs): # pragma: no cover
----------
obj : the object to write to the clipboard
excel : boolean, defaults to True
if True, use the provided separator, writing in a csv
format for allowing easy pasting into excel.
if True, use '\\t' separator and os.linesep line terminator by
default, write to csv format to allow easy pasting into excel.
if False, write a string representation of the object
to the clipboard
sep : optional, defaults to tab
other keywords are passed to to_csv
other keywords are passed to to_csv or DataFrame.to_string

Notes
-----
Expand All @@ -75,21 +74,22 @@ def to_clipboard(obj, excel=None, sep=None, **kwargs): # pragma: no cover
- OS X:
"""
from pandas.util.clipboard import clipboard_set
if excel is None:
excel = True

if excel:
try:
if sep is None:
sep = '\t'
buf = StringIO()
obj.to_csv(buf, sep=sep, **kwargs)
clipboard_set(buf.getvalue())
return
except:
pass

if isinstance(obj, DataFrame):
# COMPAT: allow None for `excel` and `sep`
if excel in (True, None) and isinstance(obj, (DataFrame, Series)):
if 'sep' not in kwargs or not kwargs['sep']:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is looking way more complicated than before.

Copy link
Contributor Author

@Winand Winand May 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to make this compatible with current to_clipboard behaviour and its tests.

  1. excel=None it's treated as True. Existing tests use None.
  2. sep=None is ignored

'Cause i thought it's better to pass sep as a kwargs item i have to check for its existense&value. Is it better to convert it back to explicit function argument?

kwargs['sep'] = '\t'
if 'line_terminator' not in kwargs:
import os
kwargs['line_terminator'] = os.linesep
buf = StringIO()
obj.to_csv(buf, **kwargs)
objstr = buf.getvalue()
elif isinstance(obj, DataFrame):
if 'sep' in kwargs:
if kwargs['sep']:
raise ValueError("sep kw is unsupported with excel=False")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe i should remove ValueError here? just delete sep kw (if it's None) for backwards compatibility. And let to_string to raise error otherwise.

del kwargs['sep'] # sep is \t
# str(df) has various unhelpful defaults, like truncation
with option_context('display.max_colwidth', 999999):
objstr = obj.to_string(**kwargs)
Expand Down
10 changes: 10 additions & 0 deletions pandas/io/tests/test_clipboard.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
import os

import numpy as np
from numpy.random import randint

Expand Down Expand Up @@ -80,6 +82,14 @@ def test_round_trip_frame(self):
for dt in self.data_types:
self.check_round_trip_frame(dt)

def test_linesep(self):
pd.DataFrame().to_clipboard()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need a fair amount more tests. these need to exercise all of the paths that are defined above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean check all self.data dataframes? But again i don't understand, we need to check only line separator. Why test dataframes with different data?

ret = pandas.util.clipboard.clipboard_get()
assert ret == '""'+os.linesep, "Wrong line separator"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to use assert_frame/series_equal.

Copy link
Contributor Author

@Winand Winand Sep 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, i check that text data in the clipboard has intended separators (os.linesep). How can this be done with assert_frame_equal?

pd.Series([0]).to_clipboard(line_terminator="\t")
ret = pandas.util.clipboard.clipboard_get()
assert ret == "0\t0\t", "Wrong line separator"

def test_read_clipboard_infer_excel(self):
from textwrap import dedent
from pandas.util.clipboard import clipboard_set
Expand Down