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

14 statements  

1"""io on the clipboard""" 

2 

3from __future__ import annotations 

4 

5from io import StringIO 

6from typing import TYPE_CHECKING 

7import warnings 

8 

9from pandas._libs import lib 

10from pandas.util._decorators import set_module 

11from pandas.util._exceptions import find_stack_level 

12from pandas.util._validators import check_dtype_backend 

13 

14from pandas.core.dtypes.generic import ABCDataFrame 

15 

16from pandas import ( 

17 get_option, 

18 option_context, 

19) 

20 

21if TYPE_CHECKING: 

22 from pandas._typing import DtypeBackend 

23 

24 

25@set_module("pandas") 

26def read_clipboard( 

27 sep: str = r"\s+", 

28 dtype_backend: DtypeBackend | lib.NoDefault = lib.no_default, 

29 **kwargs, 

30): # pragma: no cover 

31 r""" 

32 Read text from clipboard and pass to :func:`~pandas.read_csv`. 

33 

34 Parses clipboard contents similar to how CSV files are parsed 

35 using :func:`~pandas.read_csv`. 

36 

37 Parameters 

38 ---------- 

39 sep : str, default '\\s+' 

40 A string or regex delimiter. The default of ``'\\s+'`` denotes 

41 one or more whitespace characters. 

42 

43 dtype_backend : {'numpy_nullable', 'pyarrow'} 

44 Back-end data type applied to the resultant :class:`DataFrame` 

45 (still experimental). If not specified, the default behavior 

46 is to not use nullable data types. If specified, the behavior 

47 is as follows: 

48 

49 * ``"numpy_nullable"``: returns nullable-dtype-backed :class:`DataFrame` 

50 * ``"pyarrow"``: returns pyarrow-backed nullable 

51 :class:`ArrowDtype` :class:`DataFrame` 

52 

53 .. versionadded:: 2.0 

54 

55 **kwargs 

56 See :func:`~pandas.read_csv` for the full argument list. 

57 

58 Returns 

59 ------- 

60 DataFrame 

61 A parsed :class:`~pandas.DataFrame` object. 

62 

63 See Also 

64 -------- 

65 DataFrame.to_clipboard : Copy object to the system clipboard. 

66 read_csv : Read a comma-separated values (csv) file into DataFrame. 

67 read_fwf : Read a table of fixed-width formatted lines into DataFrame. 

68 

69 Examples 

70 -------- 

71 >>> df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=["A", "B", "C"]) 

72 >>> df.to_clipboard() # doctest: +SKIP 

73 >>> pd.read_clipboard() # doctest: +SKIP 

74 A B C 

75 0 1 2 3 

76 1 4 5 6 

77 """ 

78 encoding = kwargs.pop("encoding", "utf-8") 

79 

80 # only utf-8 is valid for passed value because that's what clipboard 

81 # supports 

82 if encoding is not None and encoding.lower().replace("-", "") != "utf8": 

83 raise NotImplementedError("reading from clipboard only supports utf-8 encoding") 

84 

85 check_dtype_backend(dtype_backend) 

86 

87 from pandas.io.clipboard import clipboard_get 

88 from pandas.io.parsers import read_csv 

89 

90 text = clipboard_get() 

91 

92 # Try to decode (if needed, as "text" might already be a string here). 

93 try: 

94 text = text.decode(kwargs.get("encoding") or get_option("display.encoding")) 

95 except AttributeError: 

96 pass 

97 

98 # Excel copies into clipboard with \t separation 

99 # inspect no more then the 10 first lines, if they 

100 # all contain an equal number (>0) of tabs, infer 

101 # that this came from excel and set 'sep' accordingly 

102 lines = text[:10000].split("\n")[:-1][:10] 

103 

104 # Need to remove leading white space, since read_csv 

105 # accepts: 

106 # a b 

107 # 0 1 2 

108 # 1 3 4 

109 

110 counts = {x.lstrip(" ").count("\t") for x in lines} 

111 if len(lines) > 1 and len(counts) == 1 and counts.pop() != 0: 

112 sep = "\t" 

113 # check the number of leading tabs in the first line 

114 # to account for index columns 

115 index_length = len(lines[0]) - len(lines[0].lstrip(" \t")) 

116 if index_length != 0: 

117 kwargs.setdefault("index_col", list(range(index_length))) 

118 

119 elif not isinstance(sep, str): 

120 raise ValueError(f"{sep=} must be a string") 

121 

122 # Regex separator currently only works with python engine. 

123 # Default to python if separator is multi-character (regex) 

124 if len(sep) > 1 and kwargs.get("engine") is None: 

125 kwargs["engine"] = "python" 

126 elif len(sep) > 1 and kwargs.get("engine") == "c": 

127 warnings.warn( 

128 "read_clipboard with regex separator does not work properly with c engine.", 

129 stacklevel=find_stack_level(), 

130 ) 

131 

132 return read_csv(StringIO(text), sep=sep, dtype_backend=dtype_backend, **kwargs) 

133 

134 

135def to_clipboard( 

136 obj, excel: bool | None = True, sep: str | None = None, **kwargs 

137) -> None: # pragma: no cover 

138 """ 

139 Attempt to write text representation of object to the system clipboard 

140 The clipboard can be then pasted into Excel for example. 

141 

142 Parameters 

143 ---------- 

144 obj : the object to write to the clipboard 

145 excel : bool, defaults to True 

146 if True, use the provided separator, writing in a csv 

147 format for allowing easy pasting into excel. 

148 if False, write a string representation of the object 

149 to the clipboard 

150 sep : optional, defaults to tab 

151 other keywords are passed to to_csv 

152 

153 Notes 

154 ----- 

155 Requirements for your platform 

156 - Linux: xclip, or xsel (with PyQt4 modules) 

157 - Windows: 

158 - OS X: 

159 """ 

160 encoding = kwargs.pop("encoding", "utf-8") 

161 

162 # testing if an invalid encoding is passed to clipboard 

163 if encoding is not None and encoding.lower().replace("-", "") != "utf8": 

164 raise ValueError("clipboard only supports utf-8 encoding") 

165 

166 from pandas.io.clipboard import clipboard_set 

167 

168 if excel is None: 

169 excel = True 

170 

171 if excel: 

172 try: 

173 if sep is None: 

174 sep = "\t" 

175 buf = StringIO() 

176 

177 # clipboard_set (pyperclip) expects unicode 

178 obj.to_csv(buf, sep=sep, encoding="utf-8", **kwargs) 

179 text = buf.getvalue() 

180 

181 clipboard_set(text) 

182 return 

183 except TypeError: 

184 warnings.warn( 

185 "to_clipboard in excel mode requires a single character separator.", 

186 stacklevel=find_stack_level(), 

187 ) 

188 elif sep is not None: 

189 warnings.warn( 

190 "to_clipboard with excel=False ignores the sep argument.", 

191 stacklevel=find_stack_level(), 

192 ) 

193 

194 if isinstance(obj, ABCDataFrame): 

195 # str(df) has various unhelpful defaults, like truncation 

196 with option_context("display.max_colwidth", None): 

197 objstr = obj.to_string(**kwargs) 

198 else: 

199 objstr = str(obj) 

200 clipboard_set(objstr)