Skip to content

Commit 4d589e8

Browse files
committed
TST: add basic clipboard test
Also add support for PySide
1 parent 689d491 commit 4d589e8

File tree

8 files changed

+118
-23
lines changed

8 files changed

+118
-23
lines changed

.travis.yml

+11-9
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ language: python
33
python:
44
- 2.6
55

6-
env:
7-
global:
8-
- NOSE_ARGS="not slow" UPLOAD=true
9-
106
matrix:
117
include:
8+
- python: 2.6
9+
env: NOSE_ARGS="not slow" CLIPBOARD=xclip
1210
- python: 2.7
13-
env: NOSE_ARGS="slow and not network" LOCALE_OVERRIDE="zh_CN.GB18030" FULL_DEPS=true JOB_TAG=_LOCALE
11+
env: NOSE_ARGS="slow and not network" LOCALE_OVERRIDE="zh_CN.GB18030" FULL_DEPS=true JOB_TAG=_LOCALE
1412
- python: 2.7
15-
env: NOSE_ARGS="not slow" FULL_DEPS=true
13+
env: NOSE_ARGS="not slow" FULL_DEPS=true GUI=gtk2
1614
- python: 3.2
17-
env: NOSE_ARGS="not slow" FULL_DEPS=true
15+
env: NOSE_ARGS="not slow" FULL_DEPS=true GUI=qt4
1816
- python: 3.3
19-
env: NOSE_ARGS="not slow" FULL_DEPS=true
17+
env: NOSE_ARGS="not slow" FULL_DEPS=true CLIPBOARD=xsel
18+
exclude:
19+
- python: 2.6
2020

2121
# allow importing from site-packages,
2222
# so apt-get python-x works for system pythons
@@ -27,14 +27,16 @@ virtualenv:
2727
before_install:
2828
- echo "Waldo1"
2929
- echo $VIRTUAL_ENV
30-
- df
30+
- df -h
3131
- date
3232
# - export PIP_ARGS=-q # comment this this to debug travis install issues
3333
# - export APT_ARGS=-qq # comment this to debug travis install issues
3434
# - set -x # enable this to see bash commands
3535
- export ZIP_FLAGS=-q # comment this to debug travis install issues
3636
- ci/before_install.sh
3737
- python -V
38+
- export DISPLAY=:99.0
39+
- sh -e /etc/init.d/xvfb start
3840

3941
install:
4042
- echo "Waldo2"

ci/install.sh

+16
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ fi
4141
time pip install $PIP_ARGS -r ci/requirements-${TRAVIS_PYTHON_VERSION}${JOB_TAG}.txt
4242
time sudo apt-get install libatlas-base-dev gfortran
4343

44+
45+
# install gui for clipboard testing
46+
if [ -n "$GUI" ]; then
47+
echo "Using GUI clipboard: $GUI"
48+
[ -n "$pv" ] && py="py"
49+
time sudo apt-get $APT_ARGS install python${pv}-${py}${GUI}
50+
fi
51+
52+
53+
# install a clipboard
54+
if [ -n "$CLIPBOARD" ]; then
55+
echo "Using clipboard: $CLIPBOARD"
56+
time sudo apt-get $APT_ARGS install $CLIPBOARD
57+
fi
58+
59+
4460
# Optional Deps
4561
if [ x"$FULL_DEPS" == x"true" ]; then
4662
echo "Installing FULL_DEPS"

doc/source/install.rst

+9
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ Optional Dependencies
103103
* Needed for Excel I/O
104104
* `boto <https://pypi.python.org/pypi/boto>`__: necessary for Amazon S3
105105
access.
106+
* One of `PyQt4
107+
<http://www.riverbankcomputing.com/software/pyqt/download>`__, `PySide
108+
<http://qt-project.org/wiki/Category:LanguageBindings::PySide>`__, `pygtk
109+
<http://www.pygtk.org/>`__, `xsel
110+
<http://www.vergenet.net/~conrad/software/xsel/>`__, or `xclip
111+
<http://sourceforge.net/projects/xclip/>`__: necessary to use
112+
:func:`~pandas.io.parsers.read_clipboard`. Most package managers on Linux
113+
distributions will have xclip and/or xsel immediately available for
114+
installation.
106115
* One of the following combinations of libraries is needed to use the
107116
top-level :func:`~pandas.io.html.read_html` function:
108117

doc/source/release.rst

+2
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ pandas 0.13
3232
**New features**
3333

3434
- Added ``isin`` method to DataFrame (:issue:`4211`)
35+
- Clipboard functionality now works with PySide (:issue:`4282`)
3536

3637
**Improvements to existing features**
3738

3839
- ``read_html`` now raises a ``URLError`` instead of catching and raising a
3940
``ValueError`` (:issue:`4303`, :issue:`4305`)
4041
- ``read_excel`` now supports an integer in its ``sheetname`` argument giving
4142
the index of the sheet to read in (:issue:`4301`).
43+
- Added a test for ``read_clipboard()`` and ``to_clipboard()`` (:issue:`4282`)
4244

4345
**API Changes**
4446

doc/source/v0.13.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Enhancements
1717

1818
- ``read_html`` now raises a ``URLError`` instead of catching and raising a
1919
``ValueError`` (:issue:`4303`, :issue:`4305`)
20+
- Added a test for ``read_clipboard()`` and ``to_clipboard()`` (:issue:`4282`)
21+
- Clipboard functionality now works with PySide (:issue:`4282`)
2022

2123
Bug Fixes
2224
~~~~~~~~~

pandas/io/clipboard.py

-2
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,3 @@ def to_clipboard(obj): # pragma: no cover
3131
"""
3232
from pandas.util.clipboard import clipboard_set
3333
clipboard_set(str(obj))
34-
35-

pandas/io/tests/test_clipboard.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import unittest
2+
3+
import numpy as np
4+
from numpy.random import randint
5+
6+
import nose
7+
8+
from pandas import DataFrame
9+
from pandas import read_clipboard
10+
from pandas.util import testing as tm
11+
from pandas.util.testing import makeCustomDataframe as mkdf
12+
13+
14+
try:
15+
import pandas.util.clipboard
16+
except OSError:
17+
raise nose.SkipTest("no clipboard found")
18+
19+
20+
class TestClipboard(unittest.TestCase):
21+
@classmethod
22+
def setUpClass(cls):
23+
cls.data = {}
24+
cls.data['string'] = mkdf(5, 3, c_idx_type='s', r_idx_type='i',
25+
c_idx_names=[None], r_idx_names=[None])
26+
cls.data['int'] = mkdf(5, 3, data_gen_f=lambda *args: randint(2),
27+
c_idx_type='s', r_idx_type='i',
28+
c_idx_names=[None], r_idx_names=[None])
29+
cls.data['float'] = mkdf(5, 3,
30+
data_gen_f=lambda r, c: float(r) + 0.01,
31+
c_idx_type='s', r_idx_type='i',
32+
c_idx_names=[None], r_idx_names=[None])
33+
cls.data['mixed'] = DataFrame({'a': np.arange(1.0, 6.0) + 0.01,
34+
'b': np.arange(1, 6),
35+
'c': list('abcde')})
36+
cls.data_types = cls.data.keys()
37+
38+
@classmethod
39+
def tearDownClass(cls):
40+
del cls.data_types, cls.data
41+
42+
def check_round_trip_frame(self, data_type):
43+
data = self.data[data_type]
44+
data.to_clipboard()
45+
result = read_clipboard()
46+
tm.assert_frame_equal(data, result)
47+
48+
def test_round_trip_frame(self):
49+
for dt in self.data_types:
50+
self.check_round_trip_frame(dt)

pandas/util/clipboard.py

+28-12
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444

4545
import platform, os
4646

47+
class NoClipboardProgramError(OSError):
48+
pass
49+
50+
4751
def winGetClipboard():
4852
ctypes.windll.user32.OpenClipboard(0)
4953
pcontents = ctypes.windll.user32.GetClipboardData(1) # 1 is CF_TEXT
@@ -138,23 +142,35 @@ def xselGetClipboard():
138142
if xselExists:
139143
getcb = xselGetClipboard
140144
setcb = xselSetClipboard
141-
try:
142-
import gtk
143-
getcb = gtkGetClipboard
144-
setcb = gtkSetClipboard
145-
except:
145+
else:
146146
try:
147-
import PyQt4.QtCore
148-
import PyQt4.QtGui
149-
app = QApplication([])
150-
cb = PyQt4.QtGui.QApplication.clipboard()
147+
import gtk
148+
except ImportError:
149+
try:
150+
import PyQt4 as qt4
151+
import PyQt4.QtCore
152+
import PyQt4.QtGui
153+
except ImportError:
154+
try:
155+
import PySide as qt4
156+
import PySide.QtCore
157+
import PySide.QtGui
158+
except ImportError:
159+
raise NoClipboardProgramError('Pyperclip requires the'
160+
' gtk, PyQt4, or PySide'
161+
' module installed, or '
162+
'either the xclip or '
163+
'xsel command.')
164+
app = qt4.QtGui.QApplication([])
165+
cb = qt4.QtGui.QApplication.clipboard()
151166
getcb = qtGetClipboard
152167
setcb = qtSetClipboard
153-
except:
154-
raise Exception('Pyperclip requires the gtk or PyQt4 module installed, or the xclip command.')
168+
else:
169+
getcb = gtkGetClipboard
170+
setcb = gtkSetClipboard
155171
copy = setcb
156172
paste = getcb
157173

158174
## pandas aliases
159175
clipboard_get = paste
160-
clipboard_set = copy
176+
clipboard_set = copy

0 commit comments

Comments
 (0)