Skip to content

Commit 825bbe2

Browse files
Ajay SaxenaAjay Saxena
Ajay Saxena
authored and
Ajay Saxena
committed
all files related to pyperclip are under pandas.util.clipboard
1 parent f708c2e commit 825bbe2

File tree

4 files changed

+404
-0
lines changed

4 files changed

+404
-0
lines changed

pandas/util/clipboard/__init__.py

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"""
2+
Pyperclip
3+
4+
A cross-platform clipboard module for Python. (only handles plain text for now)
5+
By Al Sweigart [email protected]
6+
BSD License
7+
8+
Usage:
9+
import pyperclip
10+
pyperclip.copy('The text to be copied to the clipboard.')
11+
spam = pyperclip.paste()
12+
13+
if not pyperclip.copy:
14+
print("Copy functionality unavailable!")
15+
16+
On Windows, no additional modules are needed.
17+
On Mac, the module uses pbcopy and pbpaste, which should come with the os.
18+
On Linux, install xclip or xsel via package manager. For example, in Debian:
19+
sudo apt-get install xclip
20+
21+
Otherwise on Linux, you will need the gtk or PyQt4 modules installed.
22+
23+
gtk and PyQt4 modules are not available for Python 3,
24+
and this module does not work with PyGObject yet.
25+
"""
26+
__version__ = '1.5.27'
27+
28+
import platform
29+
import os
30+
import subprocess
31+
from .clipboards import (init_osx_clipboard,
32+
init_gtk_clipboard, init_qt_clipboard,
33+
init_xclip_clipboard, init_xsel_clipboard,
34+
init_klipper_clipboard, init_no_clipboard)
35+
from .windows import init_windows_clipboard
36+
37+
# `import PyQt4` sys.exit()s if DISPLAY is not in the environment.
38+
# Thus, we need to detect the presence of $DISPLAY manually
39+
# and not load PyQt4 if it is absent.
40+
HAS_DISPLAY = os.getenv("DISPLAY", False)
41+
CHECK_CMD = "where" if platform.system() == "Windows" else "which"
42+
43+
44+
def _executable_exists(name):
45+
return subprocess.call([CHECK_CMD, name],
46+
stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
47+
48+
49+
def determine_clipboard():
50+
# Determine the OS/platform and set
51+
# the copy() and paste() functions accordingly.
52+
if 'cygwin' in platform.system().lower():
53+
# FIXME: pyperclip currently does not support Cygwin,
54+
# see https://github.com/asweigart/pyperclip/issues/55
55+
pass
56+
elif os.name == 'nt' or platform.system() == 'Windows':
57+
return init_windows_clipboard()
58+
if os.name == 'mac' or platform.system() == 'Darwin':
59+
return init_osx_clipboard()
60+
if HAS_DISPLAY:
61+
# Determine which command/module is installed, if any.
62+
try:
63+
import gtk # check if gtk is installed
64+
except ImportError:
65+
pass
66+
else:
67+
return init_gtk_clipboard()
68+
69+
try:
70+
import PyQt4 # check if PyQt4 is installed
71+
except ImportError:
72+
pass
73+
else:
74+
return init_qt_clipboard()
75+
76+
if _executable_exists("xclip"):
77+
return init_xclip_clipboard()
78+
if _executable_exists("xsel"):
79+
return init_xsel_clipboard()
80+
if _executable_exists("klipper") and _executable_exists("qdbus"):
81+
return init_klipper_clipboard()
82+
83+
return init_no_clipboard()
84+
85+
86+
def set_clipboard(clipboard):
87+
global copy, paste
88+
89+
clipboard_types = {'osx': init_osx_clipboard,
90+
'gtk': init_gtk_clipboard,
91+
'qt': init_qt_clipboard,
92+
'xclip': init_xclip_clipboard,
93+
'xsel': init_xsel_clipboard,
94+
'klipper': init_klipper_clipboard,
95+
'windows': init_windows_clipboard,
96+
'no': init_no_clipboard}
97+
98+
copy, paste = clipboard_types[clipboard]()
99+
100+
101+
copy, paste = determine_clipboard()
102+
103+
__all__ = ["copy", "paste"]
104+
105+
106+
# pandas aliases
107+
clipboard_get = paste
108+
clipboard_set = copy

pandas/util/clipboard/clipboards.py

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import sys
2+
import subprocess
3+
from .exceptions import PyperclipException
4+
5+
EXCEPT_MSG = """
6+
Pyperclip could not find a copy/paste mechanism for your system.
7+
For more information, please visit https://pyperclip.readthedocs.org """
8+
PY2 = sys.version_info[0] == 2
9+
text_type = unicode if PY2 else str
10+
11+
12+
def init_osx_clipboard():
13+
def copy_osx(text):
14+
p = subprocess.Popen(['pbcopy', 'w'],
15+
stdin=subprocess.PIPE, close_fds=True)
16+
p.communicate(input=text.encode('utf-8'))
17+
18+
def paste_osx():
19+
p = subprocess.Popen(['pbpaste', 'r'],
20+
stdout=subprocess.PIPE, close_fds=True)
21+
stdout, stderr = p.communicate()
22+
return stdout.decode('utf-8')
23+
24+
return copy_osx, paste_osx
25+
26+
27+
def init_gtk_clipboard():
28+
import gtk
29+
30+
def copy_gtk(text):
31+
global cb
32+
cb = gtk.Clipboard()
33+
cb.set_text(text)
34+
cb.store()
35+
36+
def paste_gtk():
37+
clipboardContents = gtk.Clipboard().wait_for_text()
38+
# for python 2, returns None if the clipboard is blank.
39+
if clipboardContents is None:
40+
return ''
41+
else:
42+
return clipboardContents
43+
44+
return copy_gtk, paste_gtk
45+
46+
47+
def init_qt_clipboard():
48+
# $DISPLAY should exist
49+
from PyQt4.QtGui import QApplication
50+
51+
app = QApplication([])
52+
53+
def copy_qt(text):
54+
cb = app.clipboard()
55+
cb.setText(text)
56+
57+
def paste_qt():
58+
cb = app.clipboard()
59+
return text_type(cb.text())
60+
61+
return copy_qt, paste_qt
62+
63+
64+
def init_xclip_clipboard():
65+
def copy_xclip(text):
66+
p = subprocess.Popen(['xclip', '-selection', 'c'],
67+
stdin=subprocess.PIPE, close_fds=True)
68+
p.communicate(input=text.encode('utf-8'))
69+
70+
def paste_xclip():
71+
p = subprocess.Popen(['xclip', '-selection', 'c', '-o'],
72+
stdout=subprocess.PIPE, close_fds=True)
73+
stdout, stderr = p.communicate()
74+
return stdout.decode('utf-8')
75+
76+
return copy_xclip, paste_xclip
77+
78+
79+
def init_xsel_clipboard():
80+
def copy_xsel(text):
81+
p = subprocess.Popen(['xsel', '-b', '-i'],
82+
stdin=subprocess.PIPE, close_fds=True)
83+
p.communicate(input=text.encode('utf-8'))
84+
85+
def paste_xsel():
86+
p = subprocess.Popen(['xsel', '-b', '-o'],
87+
stdout=subprocess.PIPE, close_fds=True)
88+
stdout, stderr = p.communicate()
89+
return stdout.decode('utf-8')
90+
91+
return copy_xsel, paste_xsel
92+
93+
94+
def init_klipper_clipboard():
95+
def copy_klipper(text):
96+
p = subprocess.Popen(
97+
['qdbus', 'org.kde.klipper', '/klipper', 'setClipboardContents',
98+
text.encode('utf-8')],
99+
stdin=subprocess.PIPE, close_fds=True)
100+
p.communicate(input=None)
101+
102+
def paste_klipper():
103+
p = subprocess.Popen(
104+
['qdbus', 'org.kde.klipper', '/klipper', 'getClipboardContents'],
105+
stdout=subprocess.PIPE, close_fds=True)
106+
stdout, stderr = p.communicate()
107+
108+
# Workaround for https://bugs.kde.org/show_bug.cgi?id=342874
109+
# TODO: https://github.com/asweigart/pyperclip/issues/43
110+
clipboardContents = stdout.decode('utf-8')
111+
# even if blank, Klipper will append a newline at the end
112+
assert len(clipboardContents) > 0
113+
# make sure that newline is there
114+
assert clipboardContents.endswith('\n')
115+
if clipboardContents.endswith('\n'):
116+
clipboardContents = clipboardContents[:-1]
117+
return clipboardContents
118+
119+
return copy_klipper, paste_klipper
120+
121+
122+
def init_no_clipboard():
123+
class ClipboardUnavailable(object):
124+
def __call__(self, *args, **kwargs):
125+
raise PyperclipException(EXCEPT_MSG)
126+
127+
if PY2:
128+
def __nonzero__(self):
129+
return False
130+
else:
131+
def __bool__(self):
132+
return False
133+
134+
return ClipboardUnavailable(), ClipboardUnavailable()

pandas/util/clipboard/exceptions.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import ctypes
2+
3+
4+
class PyperclipException(RuntimeError):
5+
pass
6+
7+
8+
class PyperclipWindowsException(PyperclipException):
9+
def __init__(self, message):
10+
message += " (%s)" % ctypes.WinError()
11+
super(PyperclipWindowsException, self).__init__(message)

0 commit comments

Comments
 (0)