Added Travis CI support

Fixed bugs / style issues to please Lord Travis

Squashed commit of the following:

commit f25048a1e1
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Sun Mar 30 02:40:47 2014 -0400

    syntax

commit cc8b69695a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Sun Mar 30 02:36:49 2014 -0400

    add size check, diff style check

commit 5d5ea065a4
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Sun Mar 30 02:16:05 2014 -0400

    travis fix

commit b154c6d997
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Sun Mar 30 02:09:41 2014 -0400

    travis, flake colored output

commit 46921dcd87
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Wed Mar 26 12:37:54 2014 -0400

    fix pyside+py3 bugs to satisfy CI

commit 1d30f3c5c7
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Wed Mar 26 11:13:18 2014 -0400

    fix py3 tests

commit 426578fa4c
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Wed Mar 26 07:39:19 2014 -0400

    fix pytest install

commit 88a13c1a71
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Wed Mar 26 00:29:29 2014 -0400

    qt5 updates

commit 51995488cc
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Wed Mar 26 00:16:04 2014 -0400

    correct py.test command for py3

commit e2b02fbcbd
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 23:50:38 2014 -0400

    fix 2nd install test

commit 4b3e3ee04a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 23:31:31 2014 -0400

    syntax error

commit 250eabdb34
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 23:13:42 2014 -0400

    look for py.test3

commit 9f9bca47c1
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 22:54:19 2014 -0400

    fix syntax

commit 0a871c6f36
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 22:47:58 2014 -0400

    output pip build log

commit dbce58d8cd
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 22:38:55 2014 -0400

    no comments allowed between shall lines

commit b79c06121d
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 20:56:35 2014 -0400

    another pip try

commit 09f4f5d82a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 13:36:09 2014 -0400

    pip correction

commit 0eedb5c18e
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 13:29:00 2014 -0400

    correct py version output

commit d9fd039be2
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 11:55:43 2014 -0400

    apt checks

commit cf95ccef86
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Tue Mar 25 10:23:10 2014 -0400

    alternate pip install method

commit bee0bcddfe
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:51:45 2014 -0400

    correct deps install

commit 963a4211fc
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:47:30 2014 -0400

    fixes

commit 0c86cd1dc2
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:31:06 2014 -0400

    permission fix

commit 5d04ef53b8
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:30:19 2014 -0400

    Fix py.test version selection

commit b0e6c7cb94
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:25:34 2014 -0400

    try another pyqt5 install method

commit 422a792866
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:12:36 2014 -0400

    syntax error

commit 533133905a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 23:04:37 2014 -0400

    fixes

commit 8d65211ba4
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 22:40:18 2014 -0400

    Add Qt5 test
    minor fixes

commit 4484efaefe
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 22:31:56 2014 -0400

    use correct py.test for python version

commit 5d2441a29b
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 22:24:27 2014 -0400

    add setup tests

commit 9291db64f2
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 21:48:43 2014 -0400

    fix py3-pyqt install

commit a7aa675c5a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 21:31:33 2014 -0400

    travis tests

commit e71cd2b23a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 21:17:15 2014 -0400

    more corrections

commit 527df3bca8
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 20:56:01 2014 -0400

    travis corrections

commit 87d65cac4a
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 20:48:02 2014 -0400

    Add flake tests
    Correct style in a few files to please Lord Travis

commit 537028f88f
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 17:36:24 2014 -0400

    minimize pyside package install
    correct line endings to satisfy Lord Travis

commit 1e3cc95e37
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 17:23:03 2014 -0400

    enable pyside, line ending check
    fix test

commit d7df4517f9
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 17:12:06 2014 -0400

    syntax fix

commit 1ad77a2155
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 17:00:30 2014 -0400

    alt. pytest install

commit 5edcc02072
Author: Luke Campagnola <luke.campagnola@gmail.com>
Date:   Mon Mar 24 16:52:33 2014 -0400

    Added initial travis.yml
This commit is contained in:
Luke Campagnola 2014-03-30 02:51:32 -04:00
parent 9c2a66ec86
commit 6b66edfd46
23 changed files with 819 additions and 315 deletions

230
.travis.yml Normal file
View File

@ -0,0 +1,230 @@
language: python
# Credit: Original .travis.yml lifted from VisPy
# Here we use anaconda for 2.6 and 3.3, since it provides the simplest
# interface for running different versions of Python. We could also use
# it for 2.7, but the Ubuntu system has installable 2.7 Qt4-GL, which
# allows for more complete testing.
notifications:
email: false
virtualenv:
system_site_packages: true
env:
# Enable python 2 and python 3 builds
# Note that the 2.6 build doesn't get flake8, and runs old versions of
# Pyglet and GLFW to make sure we deal with those correctly
#- PYTHON=2.6 QT=pyqt TEST=standard
- PYTHON=2.7 QT=pyqt TEST=extra
- PYTHON=2.7 QT=pyside TEST=standard
- PYTHON=3.2 QT=pyqt TEST=standard
- PYTHON=3.2 QT=pyside TEST=standard
#- PYTHON=3.2 QT=pyqt5 TEST=standard
before_install:
- TRAVIS_DIR=`pwd`
- travis_retry sudo apt-get update;
# - if [ "${PYTHON}" != "2.7" ]; then
# wget http://repo.continuum.io/miniconda/Miniconda-2.2.2-Linux-x86_64.sh -O miniconda.sh &&
# chmod +x miniconda.sh &&
# ./miniconda.sh -b &&
# export PATH=/home/$USER/anaconda/bin:$PATH &&
# conda update --yes conda &&
# travis_retry sudo apt-get -qq -y install libgl1-mesa-dri;
# fi;
- if [ "${TRAVIS_PULL_REQUEST}" != "false" ]; then
GIT_TARGET_EXTRA="+refs/heads/${TRAVIS_BRANCH}";
GIT_SOURCE_EXTRA="+refs/pull/${TRAVIS_PULL_REQUEST}/merge";
else
GIT_TARGET_EXTRA="";
GIT_SOURCE_EXTRA="";
fi;
# to aid in debugging
- echo ${TRAVIS_BRANCH}
- echo ${TRAVIS_REPO_SLUG}
- echo ${GIT_TARGET_EXTRA}
- echo ${GIT_SOURCE_EXTRA}
install:
# Dependencies
- if [ "${PYTHON}" == "2.7" ]; then
travis_retry sudo apt-get -qq -y install python-numpy &&
export PIP=pip &&
sudo ${PIP} install pytest &&
sudo ${PIP} install flake8 &&
export PYTEST=py.test;
else
travis_retry sudo apt-get -qq -y install python3-numpy &&
curl http://python-distribute.org/distribute_setup.py | sudo python3 &&
curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | sudo python3 &&
export PIP=pip3.2 &&
sudo ${PIP} install pytest &&
sudo ${PIP} install flake8 &&
export PYTEST=py.test-3.2;
fi;
# Qt
- if [ "${PYTHON}" == "2.7" ]; then
if [ ${QT} == 'pyqt' ]; then
travis_retry sudo apt-get -qq -y install python-qt4 python-qt4-gl;
else
travis_retry sudo apt-get -qq -y install python-pyside.qtcore python-pyside.qtgui python-pyside.qtsvg python-pyside.qtopengl;
fi;
elif [ "${PYTHON}" == "3.2" ]; then
if [ ${QT} == 'pyqt' ]; then
travis_retry sudo apt-get -qq -y install python3-pyqt4;
elif [ ${QT} == 'pyside' ]; then
travis_retry sudo apt-get -qq -y install python3-pyside;
else
${PIP} search PyQt5;
${PIP} install PyQt5;
cat /home/travis/.pip/pip.log;
fi;
else
conda create -n testenv --yes --quiet pip python=$PYTHON &&
source activate testenv &&
if [ ${QT} == 'pyqt' ]; then
conda install --yes --quiet pyside;
else
conda install --yes --quiet pyside;
fi;
fi;
# Install PyOpenGL
- if [ "${PYTHON}" == "2.7" ]; then
echo "Using OpenGL stable version (apt)";
travis_retry sudo apt-get -qq -y install python-opengl;
else
echo "Using OpenGL stable version (pip)";
${PIP} install -q PyOpenGL;
cat /home/travis/.pip/pip.log;
fi;
# Debugging helpers
- uname -a
- cat /etc/issue
- if [ "${PYTHON}" == "2.7" ]; then
python --version;
else
python3 --version;
fi;
- apt-cache search python3-pyqt
- apt-cache search python3-pyside
- apt-cache search pytest
- apt-cache search python pip
- apt-cache search python qt5
before_script:
# We need to create a (fake) display on Travis, let's use a funny resolution
- export DISPLAY=:99.0
- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1400x900x24 -ac +extension GLX +render
# Make sure everyone uses the correct python
- mkdir ~/bin && ln -s `which python${PYTHON}` ~/bin/python
- export PATH=/home/travis/bin:$PATH
- which python
- python --version
# Help color output from each test
- RESET='\033[0m';
RED='\033[00;31m';
GREEN='\033[00;32m';
YELLOW='\033[00;33m';
BLUE='\033[00;34m';
PURPLE='\033[00;35m';
CYAN='\033[00;36m';
WHITE='\033[00;37m';
start_test() {
echo -e "${BLUE}======== Starting $1 ========${RESET}";
};
check_output() {
ret=$?;
if [ $ret == 0 ]; then
echo -e "${GREEN}>>>>>> $1 passed <<<<<<${RESET}";
else
echo -e "${RED}>>>>>> $1 FAILED <<<<<<${RESET}";
fi;
return $ret;
};
- if [ "${TEST}" == "extra" ]; then
start_test "repo size check";
mkdir ~/repo-clone && cd ~/repo-clone &&
git init && git remote add -t ${TRAVIS_BRANCH} origin git://github.com/${TRAVIS_REPO_SLUG}.git &&
git fetch origin ${GIT_TARGET_EXTRA} &&
git checkout -qf FETCH_HEAD &&
git tag travis-merge-target &&
git gc --aggressive &&
TARGET_SIZE=`du -s . | sed -e "s/\t.*//"` &&
git pull origin ${GIT_SOURCE_EXTRA} &&
git gc --aggressive &&
MERGE_SIZE=`du -s . | sed -e "s/\t.*//"` &&
if [ "${MERGE_SIZE}" != "${TARGET_SIZE}" ]; then
SIZE_DIFF=`expr \( ${MERGE_SIZE} - ${TARGET_SIZE} \)`;
else
SIZE_DIFF=0;
fi;
fi;
- cd $TRAVIS_DIR
script:
# Run unit tests
- start_test "unit tests";
PYTHONPATH=. ${PYTEST} pyqtgraph/;
check_output "unit tests";
# check line endings
- if [ "${TEST}" == "extra" ]; then
start_test "line ending check";
! find ./ -name "*.py" | xargs file | grep CRLF &&
! find ./ -name "*.rst" | xargs file | grep CRLF;
check_output "line ending check";
fi;
# Check repo size does not expand too much
- if [ "${TEST}" == "extra" ]; then
start_test "repo size check";
echo -e "Estimated content size difference = ${SIZE_DIFF} kB" &&
test ${SIZE_DIFF} -lt 100;
check_output "repo size check";
fi;
# Check for style issues
- if [ "${TEST}" == "extra" ]; then
start_test "style check";
cd ~/repo-clone &&
git reset -q travis-merge-target &&
python setup.py style &&
check_output "style check";
fi;
- cd $TRAVIS_DIR
# Check install works
- start_test "install test";
sudo python${PYTHON} setup.py --quiet install;
check_output "install test";
# Check double-install fails
# Note the bash -c is because travis strips off the ! otherwise.
- start_test "double install test";
bash -c "! sudo python${PYTHON} setup.py --quiet install";
check_output "double install test";
# Check we can import pg
- start_test "import test";
echo "import sys; print(sys.path)" | python &&
cd /; echo "import pyqtgraph.examples" | python;
check_output "import test";

View File

@ -131,6 +131,10 @@ class MouseDragEvent(object):
return self.finish return self.finish
def __repr__(self): def __repr__(self):
if self.currentItem is None:
lp = self._lastScenePos
p = self._scenePos
else:
lp = self.lastPos() lp = self.lastPos()
p = self.pos() p = self.pos()
return "<MouseDragEvent (%g,%g)->(%g,%g) buttons=%d start=%s finish=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isStart()), str(self.isFinish())) return "<MouseDragEvent (%g,%g)->(%g,%g) buttons=%d start=%s finish=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isStart()), str(self.isFinish()))
@ -222,6 +226,9 @@ class MouseClickEvent(object):
def __repr__(self): def __repr__(self):
try: try:
if self.currentItem is None:
p = self._scenePos
else:
p = self.pos() p = self.pos()
return "<MouseClickEvent (%g,%g) button=%d>" % (p.x(), p.y(), int(self.button())) return "<MouseClickEvent (%g,%g) button=%d>" % (p.x(), p.y(), int(self.button()))
except: except:
@ -348,6 +355,10 @@ class HoverEvent(object):
return Point(self.currentItem.mapFromScene(self._lastScenePos)) return Point(self.currentItem.mapFromScene(self._lastScenePos))
def __repr__(self): def __repr__(self):
if self.currentItem is None:
lp = self._lastScenePos
p = self._scenePos
else:
lp = self.lastPos() lp = self.lastPos()
p = self.pos() p = self.pos()
return "<HoverEvent (%g,%g)->(%g,%g) buttons=%d enter=%s exit=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isEnter()), str(self.isExit())) return "<HoverEvent (%g,%g)->(%g,%g) buttons=%d enter=%s exit=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isEnter()), str(self.isExit()))

View File

@ -240,7 +240,8 @@ def refPathString(chain):
def objectSize(obj, ignore=None, verbose=False, depth=0, recursive=False): def objectSize(obj, ignore=None, verbose=False, depth=0, recursive=False):
"""Guess how much memory an object is using""" """Guess how much memory an object is using"""
ignoreTypes = [types.MethodType, types.UnboundMethodType, types.BuiltinMethodType, types.FunctionType, types.BuiltinFunctionType] ignoreTypes = ['MethodType', 'UnboundMethodType', 'BuiltinMethodType', 'FunctionType', 'BuiltinFunctionType']
ignoreTypes = [getattr(types, key) for key in ignoreTypes if hasattr(types, key)]
ignoreRegex = re.compile('(method-wrapper|Flag|ItemChange|Option|Mode)') ignoreRegex = re.compile('(method-wrapper|Flag|ItemChange|Option|Mode)')
@ -624,12 +625,12 @@ class ObjTracker(object):
## Which refs have disappeared since call to start() (these are only displayed once, then forgotten.) ## Which refs have disappeared since call to start() (these are only displayed once, then forgotten.)
delRefs = {} delRefs = {}
for i in self.startRefs.keys(): for i in list(self.startRefs.keys()):
if i not in refs: if i not in refs:
delRefs[i] = self.startRefs[i] delRefs[i] = self.startRefs[i]
del self.startRefs[i] del self.startRefs[i]
self.forgetRef(delRefs[i]) self.forgetRef(delRefs[i])
for i in self.newRefs.keys(): for i in list(self.newRefs.keys()):
if i not in refs: if i not in refs:
delRefs[i] = self.newRefs[i] delRefs[i] = self.newRefs[i]
del self.newRefs[i] del self.newRefs[i]
@ -667,7 +668,8 @@ class ObjTracker(object):
for k in self.startCount: for k in self.startCount:
c1[k] = c1.get(k, 0) - self.startCount[k] c1[k] = c1.get(k, 0) - self.startCount[k]
typs = list(c1.keys()) typs = list(c1.keys())
typs.sort(lambda a,b: cmp(c1[a], c1[b])) #typs.sort(lambda a,b: cmp(c1[a], c1[b]))
typs.sort(key=lambda a: c1[a])
for t in typs: for t in typs:
if c1[t] == 0: if c1[t] == 0:
continue continue
@ -767,7 +769,8 @@ class ObjTracker(object):
c = count.get(typ, [0,0]) c = count.get(typ, [0,0])
count[typ] = [c[0]+1, c[1]+objectSize(obj)] count[typ] = [c[0]+1, c[1]+objectSize(obj)]
typs = list(count.keys()) typs = list(count.keys())
typs.sort(lambda a,b: cmp(count[a][1], count[b][1])) #typs.sort(lambda a,b: cmp(count[a][1], count[b][1]))
typs.sort(key=lambda a: count[a][1])
for t in typs: for t in typs:
line = " %d\t%d\t%s" % (count[t][0], count[t][1], t) line = " %d\t%d\t%s" % (count[t][0], count[t][1], t)
@ -827,7 +830,7 @@ def describeObj(obj, depth=4, path=None, ignore=None):
def typeStr(obj): def typeStr(obj):
"""Create a more useful type string by making <instance> types report their class.""" """Create a more useful type string by making <instance> types report their class."""
typ = type(obj) typ = type(obj)
if typ == types.InstanceType: if typ == getattr(types, 'InstanceType', None):
return "<instance of %s>" % obj.__class__.__name__ return "<instance of %s>" % obj.__class__.__name__
else: else:
return str(typ) return str(typ)

View File

@ -36,7 +36,7 @@ class PrintExporter(Exporter):
dialog = QtGui.QPrintDialog(printer) dialog = QtGui.QPrintDialog(printer)
dialog.setWindowTitle("Print Document") dialog.setWindowTitle("Print Document")
if dialog.exec_() != QtGui.QDialog.Accepted: if dialog.exec_() != QtGui.QDialog.Accepted:
return; return
#dpi = QtGui.QDesktopWidget().physicalDpiX() #dpi = QtGui.QDesktopWidget().physicalDpiX()

View File

@ -1,7 +1,7 @@
from .Exporter import Exporter from .Exporter import Exporter
from ..python2_3 import asUnicode from ..python2_3 import asUnicode
from ..parametertree import Parameter from ..parametertree import Parameter
from ..Qt import QtGui, QtCore, QtSvg from ..Qt import QtGui, QtCore, QtSvg, USE_PYSIDE
from .. import debug from .. import debug
from .. import functions as fn from .. import functions as fn
import re import re
@ -219,6 +219,9 @@ def _generateItemSvg(item, nodes=None, root=None):
#if hasattr(item, 'setExportMode'): #if hasattr(item, 'setExportMode'):
#item.setExportMode(False) #item.setExportMode(False)
if USE_PYSIDE:
xmlStr = str(arr)
else:
xmlStr = bytes(arr).decode('utf-8') xmlStr = bytes(arr).decode('utf-8')
doc = xml.parseString(xmlStr) doc = xml.parseString(xmlStr)

View File

@ -1666,7 +1666,8 @@ def isosurface(data, level):
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ], dtype=np.uint16) 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0
], dtype=np.uint16)
## Table of triangles to use for filling each grid cell. ## Table of triangles to use for filling each grid cell.
## Each set of three integers tells us which three edges to ## Each set of three integers tells us which three edges to

View File

@ -486,7 +486,7 @@ class PlotCurveItem(GraphicsObject):
gl.glStencilOp(gl.GL_REPLACE, gl.GL_KEEP, gl.GL_KEEP) gl.glStencilOp(gl.GL_REPLACE, gl.GL_KEEP, gl.GL_KEEP)
## draw stencil pattern ## draw stencil pattern
gl.glStencilMask(0xFF); gl.glStencilMask(0xFF)
gl.glClear(gl.GL_STENCIL_BUFFER_BIT) gl.glClear(gl.GL_STENCIL_BUFFER_BIT)
gl.glBegin(gl.GL_TRIANGLES) gl.glBegin(gl.GL_TRIANGLES)
gl.glVertex2f(rect.x(), rect.y()) gl.glVertex2f(rect.x(), rect.y())
@ -520,7 +520,7 @@ class PlotCurveItem(GraphicsObject):
gl.glEnable(gl.GL_LINE_SMOOTH) gl.glEnable(gl.GL_LINE_SMOOTH)
gl.glEnable(gl.GL_BLEND) gl.glEnable(gl.GL_BLEND)
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST); gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
gl.glDrawArrays(gl.GL_LINE_STRIP, 0, pos.size / pos.shape[-1]) gl.glDrawArrays(gl.GL_LINE_STRIP, 0, pos.size / pos.shape[-1])
finally: finally:
gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDisableClientState(gl.GL_VERTEX_ARRAY)

View File

@ -291,15 +291,16 @@ class PlotItem(GraphicsWidget):
"""Return the :class:`ViewBox <pyqtgraph.ViewBox>` contained within.""" """Return the :class:`ViewBox <pyqtgraph.ViewBox>` contained within."""
return self.vb return self.vb
## Wrap a few methods from viewBox.
## Wrap a few methods from viewBox.
#Important: don't use a settattr(m, getattr(self.vb, m)) as we'd be leaving the viebox alive #Important: don't use a settattr(m, getattr(self.vb, m)) as we'd be leaving the viebox alive
#because we had a reference to an instance method (creating wrapper methods at runtime instead). #because we had a reference to an instance method (creating wrapper methods at runtime instead).
for m in [
'setXRange', 'setYRange', 'setXLink', 'setYLink', 'setAutoPan', 'setAutoVisible', for m in ['setXRange', 'setYRange', 'setXLink', 'setYLink', 'setAutoPan', # NOTE:
'setRange', 'autoRange', 'viewRect', 'viewRange', 'setMouseEnabled', 'setLimits', 'setAutoVisible', 'setRange', 'autoRange', 'viewRect', 'viewRange', # If you update this list, please
'enableAutoRange', 'disableAutoRange', 'setAspectLocked', 'invertY', 'setMouseEnabled', 'setLimits', 'enableAutoRange', 'disableAutoRange', # update the class docstring
'register', 'unregister']: ## NOTE: If you update this list, please update the class docstring as well. 'setAspectLocked', 'invertY', 'register', 'unregister']: # as well.
def _create_method(name): def _create_method(name):
def method(self, *args, **kwargs): def method(self, *args, **kwargs):
return getattr(self.vb, name)(*args, **kwargs) return getattr(self.vb, name)(*args, **kwargs)
@ -310,6 +311,7 @@ class PlotItem(GraphicsWidget):
del _create_method del _create_method
def setLogMode(self, x=None, y=None): def setLogMode(self, x=None, y=None):
""" """
Set log scaling for x and/or y axes. Set log scaling for x and/or y axes.

View File

@ -45,7 +45,7 @@ class GLAxisItem(GLGraphicsItem):
if self.antialias: if self.antialias:
glEnable(GL_LINE_SMOOTH) glEnable(GL_LINE_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glBegin( GL_LINES ) glBegin( GL_LINES )

View File

@ -59,7 +59,7 @@ class GLGridItem(GLGraphicsItem):
glEnable(GL_LINE_SMOOTH) glEnable(GL_LINE_SMOOTH)
glEnable(GL_BLEND) glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glBegin( GL_LINES ) glBegin( GL_LINES )

View File

@ -96,7 +96,7 @@ class GLLinePlotItem(GLGraphicsItem):
glEnable(GL_LINE_SMOOTH) glEnable(GL_LINE_SMOOTH)
glEnable(GL_BLEND) glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
if self.mode == 'line_strip': if self.mode == 'line_strip':
glDrawArrays(GL_LINE_STRIP, 0, int(self.pos.size / self.pos.shape[-1])) glDrawArrays(GL_LINE_STRIP, 0, int(self.pos.size / self.pos.shape[-1]))

View File

@ -34,8 +34,9 @@ def test_interpolateArray():
result = pg.interpolateArray(data, x) result = pg.interpolateArray(data, x)
import scipy.ndimage #import scipy.ndimage
spresult = scipy.ndimage.map_coordinates(data, x.T, order=1) #spresult = scipy.ndimage.map_coordinates(data, x.T, order=1)
spresult = np.array([ 5.92, 20. , 11. , 0. , 0. ]) # generated with the above line
assert_array_almost_equal(result, spresult) assert_array_almost_equal(result, spresult)
@ -54,7 +55,10 @@ def test_interpolateArray():
[[1.5, 0.5], [1.5, 1.0], [1.5, 1.5]]]) [[1.5, 0.5], [1.5, 1.0], [1.5, 1.5]]])
r1 = pg.interpolateArray(data, x) r1 = pg.interpolateArray(data, x)
r2 = scipy.ndimage.map_coordinates(data, x.transpose(2,0,1), order=1) #r2 = scipy.ndimage.map_coordinates(data, x.transpose(2,0,1), order=1)
r2 = np.array([[ 8.25, 11. , 16.5 ], # generated with the above line
[ 82.5 , 110. , 165. ]])
assert_array_almost_equal(r1, r2) assert_array_almost_equal(r1, r2)

View File

@ -115,6 +115,6 @@ class WinTerm(object):
# fill the entire screen with blanks # fill the entire screen with blanks
win32.FillConsoleOutputCharacter(handle, ' ', dw_con_size, coord_screen) win32.FillConsoleOutputCharacter(handle, ' ', dw_con_size, coord_screen)
# now set the buffer's attributes accordingly # now set the buffer's attributes accordingly
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen ); win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen )
# put the cursor at (0, 0) # put the cursor at (0, 0)
win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y)) win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y))

View File

@ -93,17 +93,34 @@ class Build(distutils.command.build.build):
sys.excepthook(*sys.exc_info()) sys.excepthook(*sys.exc_info())
return ret return ret
import distutils.command.install
class Install(distutils.command.install.install):
"""
* Check for previously-installed version before installing
"""
def run(self):
name = self.config_vars['dist_name']
if name in os.listdir(self.install_libbase):
raise Exception("It appears another version of %s is already "
"installed at %s; remove this before installing."
% (name, self.install_libbase))
print("Installing to %s" % self.install_libbase)
return distutils.command.install.install.run(self)
setup( setup(
version=version, version=version,
cmdclass={'build': Build, 'deb': helpers.DebCommand, 'test': helpers.TestCommand}, cmdclass={'build': Build,
'install': Install,
'deb': helpers.DebCommand,
'test': helpers.TestCommand,
'debug': helpers.DebugCommand,
'style': helpers.StyleCommand},
packages=allPackages, packages=allPackages,
package_dir={'pyqtgraph.examples': 'examples'}, ## install examples along with the rest of the source package_dir={'pyqtgraph.examples': 'examples'}, ## install examples along with the rest of the source
#package_data={'pyqtgraph': ['graphicsItems/PlotItem/*.png']}, #package_data={'pyqtgraph': ['graphicsItems/PlotItem/*.png']},
install_requires = [ install_requires = [
'numpy', 'numpy',
'scipy',
], ],
**setupOpts **setupOpts
) )

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import os, sys, re import os, sys, re
try: try:
from subprocess import check_output from subprocess import check_output
@ -9,9 +10,211 @@ except ImportError:
output = proc.stdout.read() output = proc.stdout.read()
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
raise Exception("Process had nonzero return value", proc.returncode) ex = Exception("Process had nonzero return value %d" % proc.returncode)
ex.returncode = proc.returncode
ex.output = output
raise ex
return output return output
# Paths that are checked for style by flake and flake_diff
FLAKE_CHECK_PATHS = ['pyqtgraph', 'examples', 'tools']
# Flake style checks -- mandatory, recommended, optional
# See: http://pep8.readthedocs.org/en/1.4.6/intro.html
# and https://flake8.readthedocs.org/en/2.0/warnings.html
FLAKE_MANDATORY = set([
'E101', # indentation contains mixed spaces and tabs
'E112', # expected an indented block
'E122', # continuation line missing indentation or outdented
'E125', # continuation line does not distinguish itself from next line
'E133', # closing bracket is missing indentation
'E223', # tab before operator
'E224', # tab after operator
'E242', # tab after ,
'E273', # tab after keyword
'E274', # tab before keyword
'E901', # SyntaxError or IndentationError
'E902', # IOError
'W191', # indentation contains tabs
'W601', # .has_key() is deprecated, use in
'W602', # deprecated form of raising exception
'W603', # <> is deprecated, use !=
'W604', # backticks are deprecated, use repr()
])
FLAKE_RECOMMENDED = set([
'E124', # closing bracket does not match visual indentation
'E231', # missing whitespace after ,
'E211', # whitespace before (
'E261', # at least two spaces before inline comment
'E271', # multiple spaces after keyword
'E272', # multiple spaces before keyword
'E304', # blank lines found after function decorator
'F401', # module imported but unused
'F402', # import module from line N shadowed by loop variable
'F403', # from module import * used; unable to detect undefined names
'F404', # future import(s) name after other statements
'E501', # line too long (82 > 79 characters)
'E502', # the backslash is redundant between brackets
'E702', # multiple statements on one line (semicolon)
'E703', # statement ends with a semicolon
'E711', # comparison to None should be if cond is None:
'E712', # comparison to True should be if cond is True: or if cond:
'E721', # do not compare types, use isinstance()
'F811', # redefinition of unused name from line N
'F812', # list comprehension redefines name from line N
'F821', # undefined name name
'F822', # undefined name name in __all__
'F823', # local variable name ... referenced before assignment
'F831', # duplicate argument name in function definition
'F841', # local variable name is assigned to but never used
'W292', # no newline at end of file
])
FLAKE_OPTIONAL = set([
'E121', # continuation line indentation is not a multiple of four
'E123', # closing bracket does not match indentation of opening bracket
'E126', # continuation line over-indented for hanging indent
'E127', # continuation line over-indented for visual indent
'E128', # continuation line under-indented for visual indent
'E201', # whitespace after (
'E202', # whitespace before )
'E203', # whitespace before :
'E221', # multiple spaces before operator
'E222', # multiple spaces after operator
'E225', # missing whitespace around operator
'E227', # missing whitespace around bitwise or shift operator
'E226', # missing whitespace around arithmetic operator
'E228', # missing whitespace around modulo operator
'E241', # multiple spaces after ,
'E251', # unexpected spaces around keyword / parameter equals
'E262', # inline comment should start with #
'E301', # expected 1 blank line, found 0
'E302', # expected 2 blank lines, found 0
'E303', # too many blank lines (3)
'E401', # multiple imports on one line
'E701', # multiple statements on one line (colon)
'W291', # trailing whitespace
'W293', # blank line contains whitespace
'W391', # blank line at end of file
])
FLAKE_IGNORE = set([
# 111 and 113 are ignored because they appear to be broken.
'E111', # indentation is not a multiple of four
'E113', # unexpected indentation
])
#def checkStyle():
#try:
#out = check_output(['flake8', '--select=%s' % FLAKE_TESTS, '--statistics', 'pyqtgraph/'])
#ret = 0
#print("All style checks OK.")
#except Exception as e:
#out = e.output
#ret = e.returncode
#print(out.decode('utf-8'))
#return ret
def checkStyle():
""" Run flake8, checking only lines that are modified since the last
git commit. """
test = [ 1,2,3 ]
# First check _all_ code against mandatory error codes
print('flake8: check all code against mandatory error set...')
errors = ','.join(FLAKE_MANDATORY)
cmd = ['flake8', '--select=' + errors] + FLAKE_CHECK_PATHS
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
#ret = proc.wait()
output = proc.stdout.read().decode('utf-8')
ret = proc.wait()
printFlakeOutput(output)
# Next check new code with optional error codes
print('flake8: check new code against recommended error set...')
diff = subprocess.check_output(['git', 'diff'])
proc = subprocess.Popen(['flake8', '--diff', #'--show-source',
'--ignore=' + errors],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
proc.stdin.write(diff)
proc.stdin.close()
output = proc.stdout.read().decode('utf-8')
ret |= printFlakeOutput(output)
if ret == 0:
print('flake8 test passed.')
else:
print('flake8 test failed: %d' % ret)
sys.exit(ret)
def printFlakeOutput(text):
""" Print flake output, colored by error category.
Return 2 if there were any mandatory errors,
1 if only recommended / optional errors, and
0 if only optional errors.
"""
ret = 0
gotError = False
for line in text.split('\n'):
m = re.match(r'[^\:]+\:\d+\:\d+\: (\w+) .*', line)
if m is None:
print(line)
else:
gotError = True
error = m.group(1)
if error in FLAKE_MANDATORY:
print("\033[0;31m" + line + "\033[0m")
ret |= 2
elif error in FLAKE_RECOMMENDED:
print("\033[0;33m" + line + "\033[0m")
#ret |= 1
elif error in FLAKE_OPTIONAL:
print("\033[0;32m" + line + "\033[0m")
elif error in FLAKE_IGNORE:
continue
else:
print("\033[0;36m" + line + "\033[0m")
if not gotError:
print(" [ no errors ]\n")
return ret
def unitTests():
try:
if sys.version[0] == '3':
out = check_output('PYTHONPATH=. py.test-3', shell=True)
else:
out = check_output('PYTHONPATH=. py.test', shell=True)
ret = 0
except Exception as e:
out = e.output
ret = e.returncode
print(out.decode('utf-8'))
return ret
def listAllPackages(pkgroot): def listAllPackages(pkgroot):
path = os.getcwd() path = os.getcwd()
n = len(path.split(os.path.sep)) n = len(path.split(os.path.sep))
@ -190,8 +393,8 @@ class DebCommand(Command):
raise Exception("Error during debuild.") raise Exception("Error during debuild.")
class TestCommand(Command): class DebugCommand(Command):
"""Just for learning about distutils; not for running package tests.""" """Just for learning about distutils."""
description = "" description = ""
user_options = [] user_options = []
def initialize_options(self): def initialize_options(self):
@ -203,3 +406,33 @@ class TestCommand(Command):
cmd = self cmd = self
print(self.distribution.name) print(self.distribution.name)
print(self.distribution.version) print(self.distribution.version)
class TestCommand(Command):
description = "Run all package tests and exit immediately with informative return code."
user_options = []
def run(self):
sys.exit(unitTests())
def initialize_options(self):
pass
def finalize_options(self):
pass
class StyleCommand(Command):
description = "Check all code for style, exit immediately with informative return code."
user_options = []
def run(self):
sys.exit(checkStyle())
def initialize_options(self):
pass
def finalize_options(self):
pass