1
- # Pyperclip v1.5.15
2
- # A cross-platform clipboard module for Python.
3
- # By Al Sweigart [email protected]
1
+ """
2
+ Pyperclip
4
3
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
+
6
+ BSD License
9
7
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()
19
12
13
+ if not pyperclip.copy:
14
+ print("Copy functionality unavailable!")
20
15
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
47
20
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'
49
27
50
28
import platform
51
29
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 ()
168
68
69
+ try :
70
+ import PyQt4 # check if PyQt4 is installed
71
+ except ImportError :
72
+ pass
73
+ else :
74
+ return init_qt_clipboard ()
169
75
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 ()
175
82
83
+ return init_no_clipboard ()
176
84
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' )
182
85
86
+ def set_clipboard (clipboard ):
87
+ global copy , paste
183
88
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 }
204
97
205
- xselExists = call (['which' , 'xsel' ],
206
- stdout = PIPE , stderr = PIPE ) == 0
98
+ copy , paste = clipboard_types [clipboard ]()
207
99
208
- xklipperExists = (
209
- call (['which' , 'klipper' ], stdout = PIPE , stderr = PIPE ) == 0 and
210
- call (['which' , 'qdbus' ], stdout = PIPE , stderr = PIPE ) == 0
211
- )
212
100
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 ()
220
102
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" ]
231
104
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.' )
263
105
264
106
# pandas aliases
265
107
clipboard_get = paste
266
- clipboard_set = copy
108
+ clipboard_set = copy
0 commit comments