Skip to content

Commit d565b1f

Browse files
Ajay SaxenaAjay Saxena
Ajay Saxena
authored and
Ajay Saxena
committed
updated pyperclip to the latest version
1 parent 66d8ebf commit d565b1f

File tree

4 files changed

+382
-244
lines changed

4 files changed

+382
-244
lines changed

pandas/util/clipboard.py

+86-244
Original file line numberDiff line numberDiff line change
@@ -1,266 +1,108 @@
1-
# Pyperclip v1.5.15
2-
# A cross-platform clipboard module for Python.
3-
# By Al Sweigart [email protected]
1+
"""
2+
Pyperclip
43
5-
# Usage:
6-
# import pyperclip
7-
# pyperclip.copy('The text to be copied to the clipboard.')
8-
# spam = pyperclip.paste()
4+
A cross-platform clipboard module for Python. (only handles plain text for now)
5+
By Al Sweigart [email protected]
6+
BSD License
97
10-
# On Windows, no additional modules are needed.
11-
# On Mac, this module makes use of the pbcopy and pbpaste commands, which
12-
# should come with the os.
13-
# On Linux, this module makes use of the xclip or xsel commands, which should
14-
# come with the os. Otherwise run "sudo apt-get install xclip" or
15-
# "sudo apt-get install xsel"
16-
# Otherwise on Linux, you will need the gtk or PyQt4 modules installed.
17-
# The gtk module is not available for Python 3, and this module does not work
18-
# with PyGObject yet.
8+
Usage:
9+
import pyperclip
10+
pyperclip.copy('The text to be copied to the clipboard.')
11+
spam = pyperclip.paste()
1912
13+
if not pyperclip.copy:
14+
print("Copy functionality unavailable!")
2015
21-
# Copyright (c) 2015, Albert Sweigart
22-
# All rights reserved.
23-
#
24-
# BSD-style license:
25-
#
26-
# Redistribution and use in source and binary forms, with or without
27-
# modification, are permitted provided that the following conditions are met:
28-
# * Redistributions of source code must retain the above copyright
29-
# notice, this list of conditions and the following disclaimer.
30-
# * Redistributions in binary form must reproduce the above copyright
31-
# notice, this list of conditions and the following disclaimer in the
32-
# documentation and/or other materials provided with the distribution.
33-
# * Neither the name of the pyperclip nor the
34-
# names of its contributors may be used to endorse or promote products
35-
# derived from this software without specific prior written permission.
36-
#
37-
# THIS SOFTWARE IS PROVIDED BY Albert Sweigart "AS IS" AND ANY
38-
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39-
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40-
# DISCLAIMED. IN NO EVENT SHALL Albert Sweigart BE LIABLE FOR ANY
41-
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42-
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43-
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44-
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45-
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46-
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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
4720
48-
# flake8: noqa
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'
4927

5028
import platform
5129
import os
52-
from subprocess import call, Popen, PIPE
53-
54-
PY2 = '2' == platform.python_version_tuple()[0]
55-
text_type = unicode if PY2 else str
56-
57-
58-
class NoClipboardProgramError(OSError):
59-
pass
60-
61-
62-
def _pasteWindows():
63-
CF_UNICODETEXT = 13
64-
d = ctypes.windll
65-
d.user32.OpenClipboard(0)
66-
handle = d.user32.GetClipboardData(CF_UNICODETEXT)
67-
data = ctypes.c_wchar_p(handle).value
68-
d.user32.CloseClipboard()
69-
return data
70-
71-
72-
def _copyWindows(text):
73-
GMEM_DDESHARE = 0x2000
74-
CF_UNICODETEXT = 13
75-
d = ctypes.windll # cdll expects 4 more bytes in user32.OpenClipboard(0)
76-
if not isinstance(text, text_type):
77-
text = text.decode('mbcs')
78-
79-
d.user32.OpenClipboard(0)
80-
81-
d.user32.EmptyClipboard()
82-
hCd = d.kernel32.GlobalAlloc(GMEM_DDESHARE,
83-
len(text.encode('utf-16-le')) + 2)
84-
pchData = d.kernel32.GlobalLock(hCd)
85-
ctypes.cdll.msvcrt.wcscpy(ctypes.c_wchar_p(pchData), text)
86-
d.kernel32.GlobalUnlock(hCd)
87-
d.user32.SetClipboardData(CF_UNICODETEXT, hCd)
88-
d.user32.CloseClipboard()
89-
90-
91-
def _pasteCygwin():
92-
CF_UNICODETEXT = 13
93-
d = ctypes.cdll
94-
d.user32.OpenClipboard(0)
95-
handle = d.user32.GetClipboardData(CF_UNICODETEXT)
96-
data = ctypes.c_wchar_p(handle).value
97-
d.user32.CloseClipboard()
98-
return data
99-
100-
101-
def _copyCygwin(text):
102-
GMEM_DDESHARE = 0x2000
103-
CF_UNICODETEXT = 13
104-
d = ctypes.cdll
105-
if not isinstance(text, text_type):
106-
text = text.decode('mbcs')
107-
d.user32.OpenClipboard(0)
108-
d.user32.EmptyClipboard()
109-
hCd = d.kernel32.GlobalAlloc(GMEM_DDESHARE,
110-
len(text.encode('utf-16-le')) + 2)
111-
pchData = d.kernel32.GlobalLock(hCd)
112-
ctypes.cdll.msvcrt.wcscpy(ctypes.c_wchar_p(pchData), text)
113-
d.kernel32.GlobalUnlock(hCd)
114-
d.user32.SetClipboardData(CF_UNICODETEXT, hCd)
115-
d.user32.CloseClipboard()
116-
117-
118-
def _copyOSX(text):
119-
p = Popen(['pbcopy', 'w'], stdin=PIPE, close_fds=True)
120-
p.communicate(input=text.encode('utf-8'))
121-
122-
123-
def _pasteOSX():
124-
p = Popen(['pbpaste', 'r'], stdout=PIPE, close_fds=True)
125-
stdout, stderr = p.communicate()
126-
return stdout.decode('utf-8')
127-
128-
129-
def _pasteGtk():
130-
return gtk.Clipboard().wait_for_text()
131-
132-
133-
def _copyGtk(text):
134-
global cb
135-
cb = gtk.Clipboard()
136-
cb.set_text(text)
137-
cb.store()
138-
139-
140-
def _pasteQt():
141-
return str(cb.text())
142-
143-
144-
def _copyQt(text):
145-
cb.setText(text)
146-
147-
148-
def _copyXclip(text):
149-
p = Popen(['xclip', '-selection', 'c'], stdin=PIPE, close_fds=True)
150-
p.communicate(input=text.encode('utf-8'))
151-
152-
153-
def _pasteXclip():
154-
p = Popen(['xclip', '-selection', 'c', '-o'], stdout=PIPE, close_fds=True)
155-
stdout, stderr = p.communicate()
156-
return stdout.decode('utf-8')
157-
158-
159-
def _copyXsel(text):
160-
p = Popen(['xsel', '-b', '-i'], stdin=PIPE, close_fds=True)
161-
p.communicate(input=text.encode('utf-8'))
162-
163-
164-
def _pasteXsel():
165-
p = Popen(['xsel', '-b', '-o'], stdout=PIPE, close_fds=True)
166-
stdout, stderr = p.communicate()
167-
return stdout.decode('utf-8')
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()
16868

69+
try:
70+
import PyQt4 # check if PyQt4 is installed
71+
except ImportError:
72+
pass
73+
else:
74+
return init_qt_clipboard()
16975

170-
def _copyKlipper(text):
171-
p = Popen(['qdbus', 'org.kde.klipper', '/klipper',
172-
'setClipboardContents', text.encode('utf-8')],
173-
stdin=PIPE, close_fds=True)
174-
p.communicate(input=None)
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()
17582

83+
return init_no_clipboard()
17684

177-
def _pasteKlipper():
178-
p = Popen(['qdbus', 'org.kde.klipper', '/klipper',
179-
'getClipboardContents'], stdout=PIPE, close_fds=True)
180-
stdout, stderr = p.communicate()
181-
return stdout.decode('utf-8')
18285

86+
def set_clipboard(clipboard):
87+
global copy, paste
18388

184-
# Determine the OS/platform and set the copy() and paste() functions
185-
# accordingly.
186-
if 'cygwin' in platform.system().lower():
187-
_functions = 'Cygwin' # for debugging
188-
import ctypes
189-
paste = _pasteCygwin
190-
copy = _copyCygwin
191-
elif os.name == 'nt' or platform.system() == 'Windows':
192-
_functions = 'Windows' # for debugging
193-
import ctypes
194-
paste = _pasteWindows
195-
copy = _copyWindows
196-
elif os.name == 'mac' or platform.system() == 'Darwin':
197-
_functions = 'OS X pbcopy/pbpaste' # for debugging
198-
paste = _pasteOSX
199-
copy = _copyOSX
200-
elif os.name == 'posix' or platform.system() == 'Linux':
201-
# Determine which command/module is installed, if any.
202-
xclipExists = call(['which', 'xclip'],
203-
stdout=PIPE, stderr=PIPE) == 0
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}
20497

205-
xselExists = call(['which', 'xsel'],
206-
stdout=PIPE, stderr=PIPE) == 0
98+
copy, paste = clipboard_types[clipboard]()
20799

208-
xklipperExists = (
209-
call(['which', 'klipper'], stdout=PIPE, stderr=PIPE) == 0 and
210-
call(['which', 'qdbus'], stdout=PIPE, stderr=PIPE) == 0
211-
)
212100

213-
gtkInstalled = False
214-
try:
215-
# Check it gtk is installed.
216-
import gtk
217-
gtkInstalled = True
218-
except ImportError:
219-
pass
101+
copy, paste = determine_clipboard()
220102

221-
if not gtkInstalled:
222-
# Check for either PyQt4 or PySide
223-
qtBindingInstalled = True
224-
try:
225-
from PyQt4 import QtGui
226-
except ImportError:
227-
try:
228-
from PySide import QtGui
229-
except ImportError:
230-
qtBindingInstalled = False
103+
__all__ = ["copy", "paste"]
231104

232-
# Set one of the copy & paste functions.
233-
if xclipExists:
234-
_functions = 'xclip command' # for debugging
235-
paste = _pasteXclip
236-
copy = _copyXclip
237-
elif xklipperExists:
238-
_functions = '(KDE Klipper) - qdbus (external)' # for debugging
239-
paste = _pasteKlipper
240-
copy = _copyKlipper
241-
elif gtkInstalled:
242-
_functions = 'gtk module' # for debugging
243-
paste = _pasteGtk
244-
copy = _copyGtk
245-
elif qtBindingInstalled:
246-
_functions = 'PyQt4 module' # for debugging
247-
app = QtGui.QApplication([])
248-
cb = QtGui.QApplication.clipboard()
249-
paste = _pasteQt
250-
copy = _copyQt
251-
elif xselExists:
252-
# TODO: xsel doesn't seem to work on Raspberry Pi (my test Linux
253-
# environment). Putting this as the last method tried.
254-
_functions = 'xsel command' # for debugging
255-
paste = _pasteXsel
256-
copy = _copyXsel
257-
else:
258-
raise NoClipboardProgramError('Pyperclip requires the gtk, PyQt4, or '
259-
'PySide module installed, or either the '
260-
'xclip or xsel command.')
261-
else:
262-
raise RuntimeError('pyperclip does not support your system.')
263105

264106
# pandas aliases
265107
clipboard_get = paste
266-
clipboard_set = copy
108+
clipboard_set = copy

0 commit comments

Comments
 (0)