clipboards.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. """ io on the clipboard """
  2. from io import StringIO
  3. import warnings
  4. from pandas.core.dtypes.generic import ABCDataFrame
  5. from pandas import get_option, option_context
  6. def read_clipboard(sep=r"\s+", **kwargs): # pragma: no cover
  7. r"""
  8. Read text from clipboard and pass to read_csv.
  9. Parameters
  10. ----------
  11. sep : str, default '\s+'
  12. A string or regex delimiter. The default of '\s+' denotes
  13. one or more whitespace characters.
  14. **kwargs
  15. See read_csv for the full argument list.
  16. Returns
  17. -------
  18. DataFrame
  19. A parsed DataFrame object.
  20. """
  21. encoding = kwargs.pop("encoding", "utf-8")
  22. # only utf-8 is valid for passed value because that's what clipboard
  23. # supports
  24. if encoding is not None and encoding.lower().replace("-", "") != "utf8":
  25. raise NotImplementedError("reading from clipboard only supports utf-8 encoding")
  26. from pandas.io.clipboard import clipboard_get
  27. from pandas.io.parsers import read_csv
  28. text = clipboard_get()
  29. # Try to decode (if needed, as "text" might already be a string here).
  30. try:
  31. text = text.decode(kwargs.get("encoding") or get_option("display.encoding"))
  32. except AttributeError:
  33. pass
  34. # Excel copies into clipboard with \t separation
  35. # inspect no more then the 10 first lines, if they
  36. # all contain an equal number (>0) of tabs, infer
  37. # that this came from excel and set 'sep' accordingly
  38. lines = text[:10000].split("\n")[:-1][:10]
  39. # Need to remove leading white space, since read_csv
  40. # accepts:
  41. # a b
  42. # 0 1 2
  43. # 1 3 4
  44. counts = {x.lstrip().count("\t") for x in lines}
  45. if len(lines) > 1 and len(counts) == 1 and counts.pop() != 0:
  46. sep = "\t"
  47. # Edge case where sep is specified to be None, return to default
  48. if sep is None and kwargs.get("delim_whitespace") is None:
  49. sep = r"\s+"
  50. # Regex separator currently only works with python engine.
  51. # Default to python if separator is multi-character (regex)
  52. if len(sep) > 1 and kwargs.get("engine") is None:
  53. kwargs["engine"] = "python"
  54. elif len(sep) > 1 and kwargs.get("engine") == "c":
  55. warnings.warn(
  56. "read_clipboard with regex separator does not work "
  57. "properly with c engine"
  58. )
  59. return read_csv(StringIO(text), sep=sep, **kwargs)
  60. def to_clipboard(obj, excel=True, sep=None, **kwargs): # pragma: no cover
  61. """
  62. Attempt to write text representation of object to the system clipboard
  63. The clipboard can be then pasted into Excel for example.
  64. Parameters
  65. ----------
  66. obj : the object to write to the clipboard
  67. excel : boolean, defaults to True
  68. if True, use the provided separator, writing in a csv
  69. format for allowing easy pasting into excel.
  70. if False, write a string representation of the object
  71. to the clipboard
  72. sep : optional, defaults to tab
  73. other keywords are passed to to_csv
  74. Notes
  75. -----
  76. Requirements for your platform
  77. - Linux: xclip, or xsel (with PyQt4 modules)
  78. - Windows:
  79. - OS X:
  80. """
  81. encoding = kwargs.pop("encoding", "utf-8")
  82. # testing if an invalid encoding is passed to clipboard
  83. if encoding is not None and encoding.lower().replace("-", "") != "utf8":
  84. raise ValueError("clipboard only supports utf-8 encoding")
  85. from pandas.io.clipboard import clipboard_set
  86. if excel is None:
  87. excel = True
  88. if excel:
  89. try:
  90. if sep is None:
  91. sep = "\t"
  92. buf = StringIO()
  93. # clipboard_set (pyperclip) expects unicode
  94. obj.to_csv(buf, sep=sep, encoding="utf-8", **kwargs)
  95. text = buf.getvalue()
  96. clipboard_set(text)
  97. return
  98. except TypeError:
  99. warnings.warn(
  100. "to_clipboard in excel mode requires a single character separator."
  101. )
  102. elif sep is not None:
  103. warnings.warn("to_clipboard with excel=False ignores the sep argument")
  104. if isinstance(obj, ABCDataFrame):
  105. # str(df) has various unhelpful defaults, like truncation
  106. with option_context("display.max_colwidth", None):
  107. objstr = obj.to_string(**kwargs)
  108. else:
  109. objstr = str(obj)
  110. clipboard_set(objstr)