8th day of python challenges 111-117
This commit is contained in:
126
venv/lib/python3.6/site-packages/pandas/io/clipboard/__init__.py
Normal file
126
venv/lib/python3.6/site-packages/pandas/io/clipboard/__init__.py
Normal file
@@ -0,0 +1,126 @@
|
||||
"""
|
||||
Pyperclip
|
||||
|
||||
A cross-platform clipboard module for Python. (only handles plain text for now)
|
||||
By Al Sweigart al@inventwithpython.com
|
||||
BSD License
|
||||
|
||||
Usage:
|
||||
import pyperclip
|
||||
pyperclip.copy('The text to be copied to the clipboard.')
|
||||
spam = pyperclip.paste()
|
||||
|
||||
if not pyperclip.copy:
|
||||
print("Copy functionality unavailable!")
|
||||
|
||||
On Windows, no additional modules are needed.
|
||||
On Mac, the module uses pbcopy and pbpaste, which should come with the os.
|
||||
On Linux, install xclip or xsel via package manager. For example, in Debian:
|
||||
sudo apt-get install xclip
|
||||
|
||||
Otherwise on Linux, you will need the qtpy or PyQt modules installed.
|
||||
qtpy also requires a python-qt-bindings module: PyQt4, PyQt5, PySide, PySide2
|
||||
|
||||
This module does not work with PyGObject yet.
|
||||
"""
|
||||
__version__ = "1.5.27"
|
||||
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
|
||||
from .clipboards import (
|
||||
init_klipper_clipboard,
|
||||
init_no_clipboard,
|
||||
init_osx_clipboard,
|
||||
init_qt_clipboard,
|
||||
init_xclip_clipboard,
|
||||
init_xsel_clipboard,
|
||||
)
|
||||
from .windows import init_windows_clipboard
|
||||
|
||||
# `import qtpy` sys.exit()s if DISPLAY is not in the environment.
|
||||
# Thus, we need to detect the presence of $DISPLAY manually
|
||||
# and not load qtpy if it is absent.
|
||||
HAS_DISPLAY = os.getenv("DISPLAY", False)
|
||||
CHECK_CMD = "where" if platform.system() == "Windows" else "which"
|
||||
|
||||
|
||||
def _executable_exists(name):
|
||||
return (
|
||||
subprocess.call(
|
||||
[CHECK_CMD, name], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
== 0
|
||||
)
|
||||
|
||||
|
||||
def determine_clipboard():
|
||||
# Determine the OS/platform and set
|
||||
# the copy() and paste() functions accordingly.
|
||||
if "cygwin" in platform.system().lower():
|
||||
# FIXME: pyperclip currently does not support Cygwin,
|
||||
# see https://github.com/asweigart/pyperclip/issues/55
|
||||
pass
|
||||
elif os.name == "nt" or platform.system() == "Windows":
|
||||
return init_windows_clipboard()
|
||||
if os.name == "mac" or platform.system() == "Darwin":
|
||||
return init_osx_clipboard()
|
||||
if HAS_DISPLAY:
|
||||
# Determine which command/module is installed, if any.
|
||||
try:
|
||||
# qtpy is a small abstraction layer that lets you write
|
||||
# applications using a single api call to either PyQt or PySide
|
||||
# https://pypi.org/project/QtPy
|
||||
import qtpy # noqa
|
||||
except ImportError:
|
||||
# If qtpy isn't installed, fall back on importing PyQt5, or PyQt5
|
||||
try:
|
||||
import PyQt5 # noqa
|
||||
except ImportError:
|
||||
try:
|
||||
import PyQt4 # noqa
|
||||
except ImportError:
|
||||
pass # fail fast for all non-ImportError exceptions.
|
||||
else:
|
||||
return init_qt_clipboard()
|
||||
else:
|
||||
return init_qt_clipboard()
|
||||
pass
|
||||
else:
|
||||
return init_qt_clipboard()
|
||||
|
||||
if _executable_exists("xclip"):
|
||||
return init_xclip_clipboard()
|
||||
if _executable_exists("xsel"):
|
||||
return init_xsel_clipboard()
|
||||
if _executable_exists("klipper") and _executable_exists("qdbus"):
|
||||
return init_klipper_clipboard()
|
||||
|
||||
return init_no_clipboard()
|
||||
|
||||
|
||||
def set_clipboard(clipboard):
|
||||
global copy, paste
|
||||
|
||||
clipboard_types = {
|
||||
"osx": init_osx_clipboard,
|
||||
"qt": init_qt_clipboard,
|
||||
"xclip": init_xclip_clipboard,
|
||||
"xsel": init_xsel_clipboard,
|
||||
"klipper": init_klipper_clipboard,
|
||||
"windows": init_windows_clipboard,
|
||||
"no": init_no_clipboard,
|
||||
}
|
||||
|
||||
copy, paste = clipboard_types[clipboard]()
|
||||
|
||||
|
||||
copy, paste = determine_clipboard()
|
||||
|
||||
__all__ = ["copy", "paste"]
|
||||
|
||||
|
||||
# pandas aliases
|
||||
clipboard_get = paste
|
||||
clipboard_set = copy
|
@@ -0,0 +1,129 @@
|
||||
import subprocess
|
||||
|
||||
from .exceptions import PyperclipException
|
||||
|
||||
EXCEPT_MSG = """
|
||||
Pyperclip could not find a copy/paste mechanism for your system.
|
||||
For more information, please visit https://pyperclip.readthedocs.org """
|
||||
|
||||
|
||||
def init_osx_clipboard():
|
||||
def copy_osx(text):
|
||||
p = subprocess.Popen(["pbcopy", "w"], stdin=subprocess.PIPE, close_fds=True)
|
||||
p.communicate(input=text.encode("utf-8"))
|
||||
|
||||
def paste_osx():
|
||||
p = subprocess.Popen(["pbpaste", "r"], stdout=subprocess.PIPE, close_fds=True)
|
||||
stdout, stderr = p.communicate()
|
||||
return stdout.decode("utf-8")
|
||||
|
||||
return copy_osx, paste_osx
|
||||
|
||||
|
||||
def init_qt_clipboard():
|
||||
# $DISPLAY should exist
|
||||
|
||||
# Try to import from qtpy, but if that fails try PyQt5 then PyQt4
|
||||
try:
|
||||
from qtpy.QtWidgets import QApplication
|
||||
except ImportError:
|
||||
try:
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
except ImportError:
|
||||
from PyQt4.QtGui import QApplication
|
||||
|
||||
app = QApplication.instance()
|
||||
if app is None:
|
||||
app = QApplication([])
|
||||
|
||||
def copy_qt(text):
|
||||
cb = app.clipboard()
|
||||
cb.setText(text)
|
||||
|
||||
def paste_qt():
|
||||
cb = app.clipboard()
|
||||
return str(cb.text())
|
||||
|
||||
return copy_qt, paste_qt
|
||||
|
||||
|
||||
def init_xclip_clipboard():
|
||||
def copy_xclip(text):
|
||||
p = subprocess.Popen(
|
||||
["xclip", "-selection", "c"], stdin=subprocess.PIPE, close_fds=True
|
||||
)
|
||||
p.communicate(input=text.encode("utf-8"))
|
||||
|
||||
def paste_xclip():
|
||||
p = subprocess.Popen(
|
||||
["xclip", "-selection", "c", "-o"], stdout=subprocess.PIPE, close_fds=True
|
||||
)
|
||||
stdout, stderr = p.communicate()
|
||||
return stdout.decode("utf-8")
|
||||
|
||||
return copy_xclip, paste_xclip
|
||||
|
||||
|
||||
def init_xsel_clipboard():
|
||||
def copy_xsel(text):
|
||||
p = subprocess.Popen(
|
||||
["xsel", "-b", "-i"], stdin=subprocess.PIPE, close_fds=True
|
||||
)
|
||||
p.communicate(input=text.encode("utf-8"))
|
||||
|
||||
def paste_xsel():
|
||||
p = subprocess.Popen(
|
||||
["xsel", "-b", "-o"], stdout=subprocess.PIPE, close_fds=True
|
||||
)
|
||||
stdout, stderr = p.communicate()
|
||||
return stdout.decode("utf-8")
|
||||
|
||||
return copy_xsel, paste_xsel
|
||||
|
||||
|
||||
def init_klipper_clipboard():
|
||||
def copy_klipper(text):
|
||||
p = subprocess.Popen(
|
||||
[
|
||||
"qdbus",
|
||||
"org.kde.klipper",
|
||||
"/klipper",
|
||||
"setClipboardContents",
|
||||
text.encode("utf-8"),
|
||||
],
|
||||
stdin=subprocess.PIPE,
|
||||
close_fds=True,
|
||||
)
|
||||
p.communicate(input=None)
|
||||
|
||||
def paste_klipper():
|
||||
p = subprocess.Popen(
|
||||
["qdbus", "org.kde.klipper", "/klipper", "getClipboardContents"],
|
||||
stdout=subprocess.PIPE,
|
||||
close_fds=True,
|
||||
)
|
||||
stdout, stderr = p.communicate()
|
||||
|
||||
# Workaround for https://bugs.kde.org/show_bug.cgi?id=342874
|
||||
# TODO: https://github.com/asweigart/pyperclip/issues/43
|
||||
clipboardContents = stdout.decode("utf-8")
|
||||
# even if blank, Klipper will append a newline at the end
|
||||
assert len(clipboardContents) > 0
|
||||
# make sure that newline is there
|
||||
assert clipboardContents.endswith("\n")
|
||||
if clipboardContents.endswith("\n"):
|
||||
clipboardContents = clipboardContents[:-1]
|
||||
return clipboardContents
|
||||
|
||||
return copy_klipper, paste_klipper
|
||||
|
||||
|
||||
def init_no_clipboard():
|
||||
class ClipboardUnavailable:
|
||||
def __call__(self, *args, **kwargs):
|
||||
raise PyperclipException(EXCEPT_MSG)
|
||||
|
||||
def __bool__(self):
|
||||
return False
|
||||
|
||||
return ClipboardUnavailable(), ClipboardUnavailable()
|
@@ -0,0 +1,11 @@
|
||||
import ctypes
|
||||
|
||||
|
||||
class PyperclipException(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class PyperclipWindowsException(PyperclipException):
|
||||
def __init__(self, message):
|
||||
message += " ({err})".format(err=ctypes.WinError())
|
||||
super().__init__(message)
|
184
venv/lib/python3.6/site-packages/pandas/io/clipboard/windows.py
Normal file
184
venv/lib/python3.6/site-packages/pandas/io/clipboard/windows.py
Normal file
@@ -0,0 +1,184 @@
|
||||
"""
|
||||
This module implements clipboard handling on Windows using ctypes.
|
||||
"""
|
||||
import contextlib
|
||||
import ctypes
|
||||
from ctypes import c_size_t, c_wchar, c_wchar_p, get_errno, sizeof
|
||||
import time
|
||||
|
||||
from .exceptions import PyperclipWindowsException
|
||||
|
||||
|
||||
class CheckedCall:
|
||||
def __init__(self, f):
|
||||
super().__setattr__("f", f)
|
||||
|
||||
def __call__(self, *args):
|
||||
ret = self.f(*args)
|
||||
if not ret and get_errno():
|
||||
raise PyperclipWindowsException("Error calling " + self.f.__name__)
|
||||
return ret
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
setattr(self.f, key, value)
|
||||
|
||||
|
||||
def init_windows_clipboard():
|
||||
from ctypes.wintypes import (
|
||||
HGLOBAL,
|
||||
LPVOID,
|
||||
DWORD,
|
||||
LPCSTR,
|
||||
INT,
|
||||
HWND,
|
||||
HINSTANCE,
|
||||
HMENU,
|
||||
BOOL,
|
||||
UINT,
|
||||
HANDLE,
|
||||
)
|
||||
|
||||
windll = ctypes.windll
|
||||
msvcrt = ctypes.CDLL("msvcrt")
|
||||
|
||||
safeCreateWindowExA = CheckedCall(windll.user32.CreateWindowExA)
|
||||
safeCreateWindowExA.argtypes = [
|
||||
DWORD,
|
||||
LPCSTR,
|
||||
LPCSTR,
|
||||
DWORD,
|
||||
INT,
|
||||
INT,
|
||||
INT,
|
||||
INT,
|
||||
HWND,
|
||||
HMENU,
|
||||
HINSTANCE,
|
||||
LPVOID,
|
||||
]
|
||||
safeCreateWindowExA.restype = HWND
|
||||
|
||||
safeDestroyWindow = CheckedCall(windll.user32.DestroyWindow)
|
||||
safeDestroyWindow.argtypes = [HWND]
|
||||
safeDestroyWindow.restype = BOOL
|
||||
|
||||
OpenClipboard = windll.user32.OpenClipboard
|
||||
OpenClipboard.argtypes = [HWND]
|
||||
OpenClipboard.restype = BOOL
|
||||
|
||||
safeCloseClipboard = CheckedCall(windll.user32.CloseClipboard)
|
||||
safeCloseClipboard.argtypes = []
|
||||
safeCloseClipboard.restype = BOOL
|
||||
|
||||
safeEmptyClipboard = CheckedCall(windll.user32.EmptyClipboard)
|
||||
safeEmptyClipboard.argtypes = []
|
||||
safeEmptyClipboard.restype = BOOL
|
||||
|
||||
safeGetClipboardData = CheckedCall(windll.user32.GetClipboardData)
|
||||
safeGetClipboardData.argtypes = [UINT]
|
||||
safeGetClipboardData.restype = HANDLE
|
||||
|
||||
safeSetClipboardData = CheckedCall(windll.user32.SetClipboardData)
|
||||
safeSetClipboardData.argtypes = [UINT, HANDLE]
|
||||
safeSetClipboardData.restype = HANDLE
|
||||
|
||||
safeGlobalAlloc = CheckedCall(windll.kernel32.GlobalAlloc)
|
||||
safeGlobalAlloc.argtypes = [UINT, c_size_t]
|
||||
safeGlobalAlloc.restype = HGLOBAL
|
||||
|
||||
safeGlobalLock = CheckedCall(windll.kernel32.GlobalLock)
|
||||
safeGlobalLock.argtypes = [HGLOBAL]
|
||||
safeGlobalLock.restype = LPVOID
|
||||
|
||||
safeGlobalUnlock = CheckedCall(windll.kernel32.GlobalUnlock)
|
||||
safeGlobalUnlock.argtypes = [HGLOBAL]
|
||||
safeGlobalUnlock.restype = BOOL
|
||||
|
||||
wcslen = CheckedCall(msvcrt.wcslen)
|
||||
wcslen.argtypes = [c_wchar_p]
|
||||
wcslen.restype = UINT
|
||||
|
||||
GMEM_MOVEABLE = 0x0002
|
||||
CF_UNICODETEXT = 13
|
||||
|
||||
@contextlib.contextmanager
|
||||
def window():
|
||||
"""
|
||||
Context that provides a valid Windows hwnd.
|
||||
"""
|
||||
# we really just need the hwnd, so setting "STATIC"
|
||||
# as predefined lpClass is just fine.
|
||||
hwnd = safeCreateWindowExA(
|
||||
0, b"STATIC", None, 0, 0, 0, 0, 0, None, None, None, None
|
||||
)
|
||||
try:
|
||||
yield hwnd
|
||||
finally:
|
||||
safeDestroyWindow(hwnd)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def clipboard(hwnd):
|
||||
"""
|
||||
Context manager that opens the clipboard and prevents
|
||||
other applications from modifying the clipboard content.
|
||||
"""
|
||||
# We may not get the clipboard handle immediately because
|
||||
# some other application is accessing it (?)
|
||||
# We try for at least 500ms to get the clipboard.
|
||||
t = time.time() + 0.5
|
||||
success = False
|
||||
while time.time() < t:
|
||||
success = OpenClipboard(hwnd)
|
||||
if success:
|
||||
break
|
||||
time.sleep(0.01)
|
||||
if not success:
|
||||
raise PyperclipWindowsException("Error calling OpenClipboard")
|
||||
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
safeCloseClipboard()
|
||||
|
||||
def copy_windows(text):
|
||||
# This function is heavily based on
|
||||
# http://msdn.com/ms649016#_win32_Copying_Information_to_the_Clipboard
|
||||
with window() as hwnd:
|
||||
# http://msdn.com/ms649048
|
||||
# If an application calls OpenClipboard with hwnd set to NULL,
|
||||
# EmptyClipboard sets the clipboard owner to NULL;
|
||||
# this causes SetClipboardData to fail.
|
||||
# => We need a valid hwnd to copy something.
|
||||
with clipboard(hwnd):
|
||||
safeEmptyClipboard()
|
||||
|
||||
if text:
|
||||
# http://msdn.com/ms649051
|
||||
# If the hMem parameter identifies a memory object,
|
||||
# the object must have been allocated using the
|
||||
# function with the GMEM_MOVEABLE flag.
|
||||
count = wcslen(text) + 1
|
||||
handle = safeGlobalAlloc(GMEM_MOVEABLE, count * sizeof(c_wchar))
|
||||
locked_handle = safeGlobalLock(handle)
|
||||
|
||||
ctypes.memmove(
|
||||
c_wchar_p(locked_handle),
|
||||
c_wchar_p(text),
|
||||
count * sizeof(c_wchar),
|
||||
)
|
||||
|
||||
safeGlobalUnlock(handle)
|
||||
safeSetClipboardData(CF_UNICODETEXT, handle)
|
||||
|
||||
def paste_windows():
|
||||
with clipboard(None):
|
||||
handle = safeGetClipboardData(CF_UNICODETEXT)
|
||||
if not handle:
|
||||
# GetClipboardData may return NULL with errno == NO_ERROR
|
||||
# if the clipboard is empty.
|
||||
# (Also, it may return a handle to an empty buffer,
|
||||
# but technically that's not empty)
|
||||
return ""
|
||||
return c_wchar_p(handle).value
|
||||
|
||||
return copy_windows, paste_windows
|
Reference in New Issue
Block a user