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+ 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
5028import platform
5129import 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
265107clipboard_get = paste
266- clipboard_set = copy
108+ clipboard_set = copy
0 commit comments