diff --git a/pandas/util/clipboard.py b/pandas/util/clipboard.py index bc58af8c0ea3c..9f3ee0638352f 100644 --- a/pandas/util/clipboard.py +++ b/pandas/util/clipboard.py @@ -1,119 +1,160 @@ -""" -Taken from the IPython project http://ipython.org - -Used under the terms of the BSD license -""" - -import subprocess -import sys - - -def clipboard_get(): - """ Get text from the clipboard. - """ - if sys.platform == 'win32': - try: - return win32_clipboard_get() - except Exception: - pass - elif sys.platform == 'darwin': - try: - return osx_clipboard_get() - except Exception: - pass - return tkinter_clipboard_get() - - -def clipboard_set(text): - """ Get text from the clipboard. - """ - if sys.platform == 'win32': - try: - return win32_clipboard_set(text) - except Exception: - raise - elif sys.platform == 'darwin': - try: - return osx_clipboard_set(text) - except Exception: - pass - xsel_clipboard_set(text) - - -def win32_clipboard_get(): - """ Get the current clipboard's text on Windows. - - Requires Mark Hammond's pywin32 extensions. - """ - try: - import win32clipboard - except ImportError: - message = ("Getting text from the clipboard requires the pywin32 " - "extensions: http://sourceforge.net/projects/pywin32/") - raise Exception(message) - win32clipboard.OpenClipboard() - text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) - # FIXME: convert \r\n to \n? - win32clipboard.CloseClipboard() - return text - - -def osx_clipboard_get(): - """ Get the clipboard's text on OS X. - """ - p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'], - stdout=subprocess.PIPE) - text, stderr = p.communicate() - # Text comes in with old Mac \r line endings. Change them to \n. - text = text.replace('\r', '\n') - return text - - -def tkinter_clipboard_get(): - """ Get the clipboard's text using Tkinter. - - This is the default on systems that are not Windows or OS X. It may - interfere with other UI toolkits and should be replaced with an - implementation that uses that toolkit. - """ +# Pyperclip v1.3 +# A cross-platform clipboard module for Python. (only handles plain text for now) +# By Al Sweigart al@coffeeghost.net + +# Usage: +# import pyperclip +# pyperclip.copy('The text to be copied to the clipboard.') +# spam = pyperclip.paste() + +# On Mac, this module makes use of the pbcopy and pbpaste commands, which should come with the os. +# On Linux, this module makes use of the xclip command, which should come with the os. Otherwise run "sudo apt-get install xclip" + + +# Copyright (c) 2010, Albert Sweigart +# All rights reserved. +# +# BSD-style license: +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the pyperclip nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY Albert Sweigart "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL Albert Sweigart BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Change Log: +# 1.2 Use the platform module to help determine OS. +# 1.3 Changed ctypes.windll.user32.OpenClipboard(None) to ctypes.windll.user32.OpenClipboard(0), after some people ran into some TypeError + +import platform, os + +def winGetClipboard(): + ctypes.windll.user32.OpenClipboard(0) + pcontents = ctypes.windll.user32.GetClipboardData(1) # 1 is CF_TEXT + data = ctypes.c_char_p(pcontents).value + #ctypes.windll.kernel32.GlobalUnlock(pcontents) + ctypes.windll.user32.CloseClipboard() + return data + +def winSetClipboard(text): + GMEM_DDESHARE = 0x2000 + ctypes.windll.user32.OpenClipboard(0) + ctypes.windll.user32.EmptyClipboard() try: - import Tkinter - except ImportError: - message = ("Getting text from the clipboard on this platform " - "requires Tkinter.") - raise Exception(message) - root = Tkinter.Tk() - root.withdraw() - text = root.clipboard_get() - root.destroy() - return text - - -def win32_clipboard_set(text): - # idiosyncratic win32 import issues - import pywintypes as _ - import win32clipboard - win32clipboard.OpenClipboard() + # works on Python 2 (bytes() only takes one argument) + hCd = ctypes.windll.kernel32.GlobalAlloc(GMEM_DDESHARE, len(bytes(text))+1) + except TypeError: + # works on Python 3 (bytes() requires an encoding) + hCd = ctypes.windll.kernel32.GlobalAlloc(GMEM_DDESHARE, len(bytes(text, 'ascii'))+1) + pchData = ctypes.windll.kernel32.GlobalLock(hCd) try: - win32clipboard.EmptyClipboard() - win32clipboard.SetClipboardText(_fix_line_endings(text)) - finally: - win32clipboard.CloseClipboard() - - -def _fix_line_endings(text): - return '\r\n'.join(text.splitlines()) - - -def osx_clipboard_set(text): - """ Get the clipboard's text on OS X. - """ - p = subprocess.Popen(['pbcopy', '-Prefer', 'ascii'], - stdin=subprocess.PIPE) - p.communicate(input=text) - - -def xsel_clipboard_set(text): - from subprocess import Popen, PIPE - p = Popen(['xsel', '-bi'], stdin=PIPE) - p.communicate(input=text) + # works on Python 2 (bytes() only takes one argument) + ctypes.cdll.msvcrt.strcpy(ctypes.c_char_p(pchData), bytes(text)) + except TypeError: + # works on Python 3 (bytes() requires an encoding) + ctypes.cdll.msvcrt.strcpy(ctypes.c_char_p(pchData), bytes(text, 'ascii')) + ctypes.windll.kernel32.GlobalUnlock(hCd) + ctypes.windll.user32.SetClipboardData(1,hCd) + ctypes.windll.user32.CloseClipboard() + +def macSetClipboard(text): + outf = os.popen('pbcopy', 'w') + outf.write(text) + outf.close() + +def macGetClipboard(): + outf = os.popen('pbpaste', 'r') + content = outf.read() + outf.close() + return content + +def gtkGetClipboard(): + return gtk.Clipboard().wait_for_text() + +def gtkSetClipboard(text): + cb = gtk.Clipboard() + cb.set_text(text) + cb.store() + +def qtGetClipboard(): + return str(cb.text()) + +def qtSetClipboard(text): + cb.setText(text) + +def xclipSetClipboard(text): + outf = os.popen('xclip -selection c', 'w') + outf.write(text) + outf.close() + +def xclipGetClipboard(): + outf = os.popen('xclip -selection c -o', 'r') + content = outf.read() + outf.close() + return content + +def xselSetClipboard(text): + outf = os.popen('xsel -i', 'w') + outf.write(text) + outf.close() + +def xselGetClipboard(): + outf = os.popen('xsel -o', 'r') + content = outf.read() + outf.close() + return content + + +if os.name == 'nt' or platform.system() == 'Windows': + import ctypes + getcb = winGetClipboard + setcb = winSetClipboard +elif os.name == 'mac' or platform.system() == 'Darwin': + getcb = macGetClipboard + setcb = macSetClipboard +elif os.name == 'posix' or platform.system() == 'Linux': + xclipExists = os.system('which xclip') == 0 + if xclipExists: + getcb = xclipGetClipboard + setcb = xclipSetClipboard + else: + xselExists = os.system('which xsel') == 0 + if xselExists: + getcb = xselGetClipboard + setcb = xselSetClipboard + try: + import gtk + getcb = gtkGetClipboard + setcb = gtkSetClipboard + except: + try: + import PyQt4.QtCore + import PyQt4.QtGui + app = QApplication([]) + cb = PyQt4.QtGui.QApplication.clipboard() + getcb = qtGetClipboard + setcb = qtSetClipboard + except: + raise Exception('Pyperclip requires the gtk or PyQt4 module installed, or the xclip command.') +copy = setcb +paste = getcb + +## pandas aliases +clipboard_get = paste +clipboard_set = copy \ No newline at end of file