Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/io/clipboards.py: 93%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""io on the clipboard"""
3from __future__ import annotations
5from io import StringIO
6from typing import TYPE_CHECKING
7import warnings
9from pandas._config.config import _global_config as config
11from pandas._libs import lib
12from pandas.util._decorators import set_module
13from pandas.util._exceptions import find_stack_level
14from pandas.util._validators import check_dtype_backend
16from pandas.core.dtypes.generic import ABCDataFrame
18from pandas import option_context
20if TYPE_CHECKING:
21 from pandas._typing import DtypeBackend
24@set_module("pandas")
25def read_clipboard(
26 sep: str = r"\s+",
27 dtype_backend: DtypeBackend | lib.NoDefault = lib.no_default,
28 **kwargs,
29): # pragma: no cover
30 r"""
31 Read text from clipboard and pass to :func:`~pandas.read_csv`.
33 Parses clipboard contents similar to how CSV files are parsed
34 using :func:`~pandas.read_csv`.
36 Parameters
37 ----------
38 sep : str, default '\\s+'
39 A string or regex delimiter. The default of ``'\\s+'`` denotes
40 one or more whitespace characters.
42 dtype_backend : {'numpy_nullable', 'pyarrow'}
43 Back-end data type applied to the resultant :class:`DataFrame`
44 (still experimental). If not specified, the default behavior
45 is to not use nullable data types. If specified, the behavior
46 is as follows:
48 * ``"numpy_nullable"``: returns nullable-dtype-backed :class:`DataFrame`
49 * ``"pyarrow"``: returns pyarrow-backed nullable
50 :class:`ArrowDtype` :class:`DataFrame`
52 .. versionadded:: 2.0
54 **kwargs
55 See :func:`~pandas.read_csv` for the full argument list.
57 Returns
58 -------
59 DataFrame
60 A parsed :class:`~pandas.DataFrame` object.
62 See Also
63 --------
64 DataFrame.to_clipboard : Copy object to the system clipboard.
65 read_csv : Read a comma-separated values (csv) file into DataFrame.
66 read_fwf : Read a table of fixed-width formatted lines into DataFrame.
68 Examples
69 --------
70 >>> df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=["A", "B", "C"])
71 >>> df.to_clipboard() # doctest: +SKIP
72 >>> pd.read_clipboard() # doctest: +SKIP
73 A B C
74 0 1 2 3
75 1 4 5 6
76 """
77 encoding = kwargs.pop("encoding", "utf-8")
79 # only utf-8 is valid for passed value because that's what clipboard
80 # supports
81 if encoding is not None and encoding.lower().replace("-", "") != "utf8":
82 raise NotImplementedError("reading from clipboard only supports utf-8 encoding")
84 check_dtype_backend(dtype_backend)
86 from pandas.io.clipboard import clipboard_get
87 from pandas.io.parsers import read_csv
89 text = clipboard_get()
91 # Try to decode (if needed, as "text" might already be a string here).
92 try:
93 text = text.decode(kwargs.get("encoding") or config["display"]["encoding"])
94 except AttributeError:
95 pass
97 # Excel copies into clipboard with \t separation
98 # inspect no more than the 10 first lines, if they
99 # all contain an equal number (>0) of tabs, infer
100 # that this came from excel and set 'sep' accordingly
101 lines = text[:10000].split("\n")[:-1][:10] # pyright: ignore[reportOptionalSubscript]
103 # Need to remove leading white space, since read_csv
104 # accepts:
105 # a b
106 # 0 1 2
107 # 1 3 4
109 counts = {x.lstrip(" ").count("\t") for x in lines}
110 if len(lines) > 1 and len(counts) == 1 and counts.pop() != 0:
111 sep = "\t"
112 # check the number of leading tabs in the first line
113 # to account for index columns
114 index_length = len(lines[0]) - len(lines[0].lstrip(" \t"))
115 if index_length != 0:
116 kwargs.setdefault("index_col", list(range(index_length)))
118 elif not isinstance(sep, str):
119 raise ValueError(f"{sep=} must be a string")
121 # Regex separator currently only works with python engine.
122 # Default to python if separator is multi-character (regex)
123 if len(sep) > 1 and kwargs.get("engine") is None:
124 kwargs["engine"] = "python"
125 elif len(sep) > 1 and kwargs.get("engine") == "c":
126 warnings.warn(
127 "read_clipboard with regex separator does not work properly with c engine.",
128 stacklevel=find_stack_level(),
129 )
131 return read_csv(StringIO(text), sep=sep, dtype_backend=dtype_backend, **kwargs)
134def to_clipboard(
135 obj, excel: bool | None = True, sep: str | None = None, **kwargs
136) -> None: # pragma: no cover
137 """
138 Attempt to write text representation of object to the system clipboard
139 The clipboard can be then pasted into Excel for example.
141 Parameters
142 ----------
143 obj : the object to write to the clipboard
144 excel : bool, defaults to True
145 if True, use the provided separator, writing in a csv
146 format for allowing easy pasting into excel.
147 if False, write a string representation of the object
148 to the clipboard
149 sep : optional, defaults to tab
150 other keywords are passed to to_csv
152 Notes
153 -----
154 Requirements for your platform
155 - Linux: xclip, or xsel (with PyQt4 modules)
156 - Windows:
157 - OS X:
158 """
159 encoding = kwargs.pop("encoding", "utf-8")
161 # testing if an invalid encoding is passed to clipboard
162 if encoding is not None and encoding.lower().replace("-", "") != "utf8":
163 raise ValueError("clipboard only supports utf-8 encoding")
165 from pandas.io.clipboard import clipboard_set
167 if excel is None:
168 excel = True
170 if excel:
171 if sep is None:
172 sep = "\t"
174 # Validate sep here rather than catching to_csv's TypeError, which would
175 # also blame sep for unrelated failures such as a bad keyword (GH#44120)
176 if isinstance(sep, str) and len(sep) == 1:
177 buf = StringIO()
179 # clipboard_set (pyperclip) expects unicode
180 obj.to_csv(buf, sep=sep, encoding="utf-8", **kwargs)
181 text = buf.getvalue()
183 clipboard_set(text)
184 return
186 warnings.warn(
187 "to_clipboard in excel mode requires a single character separator.",
188 stacklevel=find_stack_level(),
189 )
190 elif sep is not None:
191 warnings.warn(
192 "to_clipboard with excel=False ignores the sep argument.",
193 stacklevel=find_stack_level(),
194 )
196 if isinstance(obj, ABCDataFrame):
197 # str(df) has various unhelpful defaults, like truncation
198 with option_context("display.max_colwidth", None):
199 objstr = obj.to_string(**kwargs)
200 else:
201 objstr = str(obj)
202 clipboard_set(objstr)