Added Travis CI support
Fixed bugs / style issues to please Lord Travis Squashed commit of the following: commitf25048a1e1
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Sun Mar 30 02:40:47 2014 -0400 syntax commitcc8b69695a
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Sun Mar 30 02:36:49 2014 -0400 add size check, diff style check commit5d5ea065a4
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Sun Mar 30 02:16:05 2014 -0400 travis fix commitb154c6d997
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Sun Mar 30 02:09:41 2014 -0400 travis, flake colored output commit46921dcd87
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Wed Mar 26 12:37:54 2014 -0400 fix pyside+py3 bugs to satisfy CI commit1d30f3c5c7
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Wed Mar 26 11:13:18 2014 -0400 fix py3 tests commit426578fa4c
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Wed Mar 26 07:39:19 2014 -0400 fix pytest install commit88a13c1a71
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Wed Mar 26 00:29:29 2014 -0400 qt5 updates commit51995488cc
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Wed Mar 26 00:16:04 2014 -0400 correct py.test command for py3 commite2b02fbcbd
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 23:50:38 2014 -0400 fix 2nd install test commit4b3e3ee04a
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 23:31:31 2014 -0400 syntax error commit250eabdb34
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 23:13:42 2014 -0400 look for py.test3 commit9f9bca47c1
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 22:54:19 2014 -0400 fix syntax commit0a871c6f36
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 22:47:58 2014 -0400 output pip build log commitdbce58d8cd
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 22:38:55 2014 -0400 no comments allowed between shall lines commitb79c06121d
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 20:56:35 2014 -0400 another pip try commit09f4f5d82a
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 13:36:09 2014 -0400 pip correction commit0eedb5c18e
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 13:29:00 2014 -0400 correct py version output commitd9fd039be2
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 11:55:43 2014 -0400 apt checks commitcf95ccef86
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Tue Mar 25 10:23:10 2014 -0400 alternate pip install method commitbee0bcddfe
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:51:45 2014 -0400 correct deps install commit963a4211fc
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:47:30 2014 -0400 fixes commit0c86cd1dc2
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:31:06 2014 -0400 permission fix commit5d04ef53b8
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:30:19 2014 -0400 Fix py.test version selection commitb0e6c7cb94
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:25:34 2014 -0400 try another pyqt5 install method commit422a792866
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:12:36 2014 -0400 syntax error commit533133905a
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 23:04:37 2014 -0400 fixes commit8d65211ba4
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 22:40:18 2014 -0400 Add Qt5 test minor fixes commit4484efaefe
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 22:31:56 2014 -0400 use correct py.test for python version commit5d2441a29b
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 22:24:27 2014 -0400 add setup tests commit9291db64f2
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 21:48:43 2014 -0400 fix py3-pyqt install commita7aa675c5a
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 21:31:33 2014 -0400 travis tests commite71cd2b23a
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 21:17:15 2014 -0400 more corrections commit527df3bca8
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 20:56:01 2014 -0400 travis corrections commit87d65cac4a
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 commit537028f88f
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 commit1e3cc95e37
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 17:23:03 2014 -0400 enable pyside, line ending check fix test commitd7df4517f9
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 17:12:06 2014 -0400 syntax fix commit1ad77a2155
Author: Luke Campagnola <luke.campagnola@gmail.com> Date: Mon Mar 24 17:00:30 2014 -0400 alt. pytest install commit5edcc02072
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:
parent
9c2a66ec86
commit
6b66edfd46
230
.travis.yml
Normal file
230
.travis.yml
Normal 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";
|
||||||
|
|
||||||
|
|
@ -131,8 +131,12 @@ class MouseDragEvent(object):
|
|||||||
return self.finish
|
return self.finish
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
lp = self.lastPos()
|
if self.currentItem is None:
|
||||||
p = self.pos()
|
lp = self._lastScenePos
|
||||||
|
p = self._scenePos
|
||||||
|
else:
|
||||||
|
lp = self.lastPos()
|
||||||
|
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()))
|
||||||
|
|
||||||
def modifiers(self):
|
def modifiers(self):
|
||||||
@ -222,7 +226,10 @@ class MouseClickEvent(object):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
try:
|
try:
|
||||||
p = self.pos()
|
if self.currentItem is None:
|
||||||
|
p = self._scenePos
|
||||||
|
else:
|
||||||
|
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:
|
||||||
return "<MouseClickEvent button=%d>" % (int(self.button()))
|
return "<MouseClickEvent button=%d>" % (int(self.button()))
|
||||||
@ -348,8 +355,12 @@ class HoverEvent(object):
|
|||||||
return Point(self.currentItem.mapFromScene(self._lastScenePos))
|
return Point(self.currentItem.mapFromScene(self._lastScenePos))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
lp = self.lastPos()
|
if self.currentItem is None:
|
||||||
p = self.pos()
|
lp = self._lastScenePos
|
||||||
|
p = self._scenePos
|
||||||
|
else:
|
||||||
|
lp = self.lastPos()
|
||||||
|
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()))
|
||||||
|
|
||||||
def modifiers(self):
|
def modifiers(self):
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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,7 +219,10 @@ def _generateItemSvg(item, nodes=None, root=None):
|
|||||||
#if hasattr(item, 'setExportMode'):
|
#if hasattr(item, 'setExportMode'):
|
||||||
#item.setExportMode(False)
|
#item.setExportMode(False)
|
||||||
|
|
||||||
xmlStr = bytes(arr).decode('utf-8')
|
if USE_PYSIDE:
|
||||||
|
xmlStr = str(arr)
|
||||||
|
else:
|
||||||
|
xmlStr = bytes(arr).decode('utf-8')
|
||||||
doc = xml.parseString(xmlStr)
|
doc = xml.parseString(xmlStr)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -29,7 +29,7 @@ def eq(a, b):
|
|||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
if (hasattr(e, 'implements') and e.implements('MetaArray')):
|
if (hasattr(e, 'implements') and e.implements('MetaArray')):
|
||||||
return e.asarray().all()
|
return e.asarray().all()
|
||||||
else:
|
else:
|
||||||
return e.all()
|
return e.all()
|
||||||
else:
|
else:
|
||||||
|
@ -328,7 +328,7 @@ class ColumnJoinNode(Node):
|
|||||||
|
|
||||||
## Node.restoreState should have created all of the terminals we need
|
## Node.restoreState should have created all of the terminals we need
|
||||||
## However: to maintain support for some older flowchart files, we need
|
## However: to maintain support for some older flowchart files, we need
|
||||||
## to manually add any terminals that were not taken care of.
|
## to manually add any terminals that were not taken care of.
|
||||||
for name in [n for n in state['order'] if n not in inputs]:
|
for name in [n for n in state['order'] if n not in inputs]:
|
||||||
Node.addInput(self, name, renamable=True, removable=True, multiable=True)
|
Node.addInput(self, name, renamable=True, removable=True, multiable=True)
|
||||||
inputs = self.inputs()
|
inputs = self.inputs()
|
||||||
|
@ -1,52 +1,52 @@
|
|||||||
## Definitions helpful in frozen environments (eg py2exe)
|
## Definitions helpful in frozen environments (eg py2exe)
|
||||||
import os, sys, zipfile
|
import os, sys, zipfile
|
||||||
|
|
||||||
def listdir(path):
|
def listdir(path):
|
||||||
"""Replacement for os.listdir that works in frozen environments."""
|
"""Replacement for os.listdir that works in frozen environments."""
|
||||||
if not hasattr(sys, 'frozen'):
|
if not hasattr(sys, 'frozen'):
|
||||||
return os.listdir(path)
|
return os.listdir(path)
|
||||||
|
|
||||||
(zipPath, archivePath) = splitZip(path)
|
(zipPath, archivePath) = splitZip(path)
|
||||||
if archivePath is None:
|
if archivePath is None:
|
||||||
return os.listdir(path)
|
return os.listdir(path)
|
||||||
|
|
||||||
with zipfile.ZipFile(zipPath, "r") as zipobj:
|
with zipfile.ZipFile(zipPath, "r") as zipobj:
|
||||||
contents = zipobj.namelist()
|
contents = zipobj.namelist()
|
||||||
results = set()
|
results = set()
|
||||||
for name in contents:
|
for name in contents:
|
||||||
# components in zip archive paths are always separated by forward slash
|
# components in zip archive paths are always separated by forward slash
|
||||||
if name.startswith(archivePath) and len(name) > len(archivePath):
|
if name.startswith(archivePath) and len(name) > len(archivePath):
|
||||||
name = name[len(archivePath):].split('/')[0]
|
name = name[len(archivePath):].split('/')[0]
|
||||||
results.add(name)
|
results.add(name)
|
||||||
return list(results)
|
return list(results)
|
||||||
|
|
||||||
def isdir(path):
|
def isdir(path):
|
||||||
"""Replacement for os.path.isdir that works in frozen environments."""
|
"""Replacement for os.path.isdir that works in frozen environments."""
|
||||||
if not hasattr(sys, 'frozen'):
|
if not hasattr(sys, 'frozen'):
|
||||||
return os.path.isdir(path)
|
return os.path.isdir(path)
|
||||||
|
|
||||||
(zipPath, archivePath) = splitZip(path)
|
(zipPath, archivePath) = splitZip(path)
|
||||||
if archivePath is None:
|
if archivePath is None:
|
||||||
return os.path.isdir(path)
|
return os.path.isdir(path)
|
||||||
with zipfile.ZipFile(zipPath, "r") as zipobj:
|
with zipfile.ZipFile(zipPath, "r") as zipobj:
|
||||||
contents = zipobj.namelist()
|
contents = zipobj.namelist()
|
||||||
archivePath = archivePath.rstrip('/') + '/' ## make sure there's exactly one '/' at the end
|
archivePath = archivePath.rstrip('/') + '/' ## make sure there's exactly one '/' at the end
|
||||||
for c in contents:
|
for c in contents:
|
||||||
if c.startswith(archivePath):
|
if c.startswith(archivePath):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def splitZip(path):
|
def splitZip(path):
|
||||||
"""Splits a path containing a zip file into (zipfile, subpath).
|
"""Splits a path containing a zip file into (zipfile, subpath).
|
||||||
If there is no zip file, returns (path, None)"""
|
If there is no zip file, returns (path, None)"""
|
||||||
components = os.path.normpath(path).split(os.sep)
|
components = os.path.normpath(path).split(os.sep)
|
||||||
for index, component in enumerate(components):
|
for index, component in enumerate(components):
|
||||||
if component.endswith('.zip'):
|
if component.endswith('.zip'):
|
||||||
zipPath = os.sep.join(components[0:index+1])
|
zipPath = os.sep.join(components[0:index+1])
|
||||||
archivePath = ''.join([x+'/' for x in components[index+1:]])
|
archivePath = ''.join([x+'/' for x in components[index+1:]])
|
||||||
return (zipPath, archivePath)
|
return (zipPath, archivePath)
|
||||||
else:
|
else:
|
||||||
return (path, None)
|
return (path, None)
|
||||||
|
|
||||||
|
|
@ -1424,30 +1424,30 @@ def isocurve(data, level, connected=False, extendToEdge=False, path=False):
|
|||||||
data = d2
|
data = d2
|
||||||
|
|
||||||
sideTable = [
|
sideTable = [
|
||||||
[],
|
[],
|
||||||
[0,1],
|
[0,1],
|
||||||
[1,2],
|
[1,2],
|
||||||
[0,2],
|
[0,2],
|
||||||
[0,3],
|
[0,3],
|
||||||
[1,3],
|
[1,3],
|
||||||
[0,1,2,3],
|
[0,1,2,3],
|
||||||
[2,3],
|
[2,3],
|
||||||
[2,3],
|
[2,3],
|
||||||
[0,1,2,3],
|
[0,1,2,3],
|
||||||
[1,3],
|
[1,3],
|
||||||
[0,3],
|
[0,3],
|
||||||
[0,2],
|
[0,2],
|
||||||
[1,2],
|
[1,2],
|
||||||
[0,1],
|
[0,1],
|
||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
|
|
||||||
edgeKey=[
|
edgeKey=[
|
||||||
[(0,1), (0,0)],
|
[(0,1), (0,0)],
|
||||||
[(0,0), (1,0)],
|
[(0,0), (1,0)],
|
||||||
[(1,0), (1,1)],
|
[(1,0), (1,1)],
|
||||||
[(1,1), (0,1)]
|
[(1,1), (0,1)]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
@ -1635,38 +1635,39 @@ def isosurface(data, level):
|
|||||||
## edge index tells us which edges are cut by the isosurface.
|
## edge index tells us which edges are cut by the isosurface.
|
||||||
## (Data stolen from Bourk; see above.)
|
## (Data stolen from Bourk; see above.)
|
||||||
edgeTable = np.array([
|
edgeTable = np.array([
|
||||||
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
|
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
|
||||||
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
|
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
|
||||||
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
|
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
|
||||||
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
|
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
|
||||||
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
|
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
|
||||||
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
|
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
|
||||||
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
|
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
|
||||||
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
|
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
|
||||||
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
|
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
|
||||||
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
|
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
|
||||||
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
|
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
|
||||||
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
||||||
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
|
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
|
||||||
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
|
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
|
||||||
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
|
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
|
||||||
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
||||||
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
|
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
|
||||||
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
||||||
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
|
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
|
||||||
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
|
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
|
||||||
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
|
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
|
||||||
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
||||||
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
|
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
|
||||||
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
|
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
|
||||||
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
|
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
|
||||||
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
|
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
|
||||||
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
|
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
|
||||||
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
|
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
|
||||||
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
|
||||||
|
@ -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)
|
||||||
|
@ -290,16 +290,17 @@ class PlotItem(GraphicsWidget):
|
|||||||
def getViewBox(self):
|
def getViewBox(self):
|
||||||
"""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.
|
||||||
|
@ -579,7 +579,7 @@ class Request(object):
|
|||||||
return self._result
|
return self._result
|
||||||
|
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self.timeout
|
timeout = self.timeout
|
||||||
|
|
||||||
if block:
|
if block:
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
@ -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 )
|
||||||
|
|
||||||
|
@ -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 )
|
||||||
|
|
||||||
|
@ -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]))
|
||||||
|
@ -1,127 +1,127 @@
|
|||||||
# Copyright (c) 2009 Raymond Hettinger
|
# Copyright (c) 2009 Raymond Hettinger
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person
|
# Permission is hereby granted, free of charge, to any person
|
||||||
# obtaining a copy of this software and associated documentation files
|
# obtaining a copy of this software and associated documentation files
|
||||||
# (the "Software"), to deal in the Software without restriction,
|
# (the "Software"), to deal in the Software without restriction,
|
||||||
# including without limitation the rights to use, copy, modify, merge,
|
# including without limitation the rights to use, copy, modify, merge,
|
||||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
# and to permit persons to whom the Software is furnished to do so,
|
# and to permit persons to whom the Software is furnished to do so,
|
||||||
# subject to the following conditions:
|
# subject to the following conditions:
|
||||||
#
|
#
|
||||||
# The above copyright notice and this permission notice shall be
|
# The above copyright notice and this permission notice shall be
|
||||||
# included in all copies or substantial portions of the Software.
|
# included in all copies or substantial portions of the Software.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
# OTHER DEALINGS IN THE SOFTWARE.
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
from UserDict import DictMixin
|
from UserDict import DictMixin
|
||||||
|
|
||||||
class OrderedDict(dict, DictMixin):
|
class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
def __init__(self, *args, **kwds):
|
def __init__(self, *args, **kwds):
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||||
try:
|
try:
|
||||||
self.__end
|
self.__end
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.clear()
|
self.clear()
|
||||||
self.update(*args, **kwds)
|
self.update(*args, **kwds)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.__end = end = []
|
self.__end = end = []
|
||||||
end += [None, end, end] # sentinel node for doubly linked list
|
end += [None, end, end] # sentinel node for doubly linked list
|
||||||
self.__map = {} # key --> [key, prev, next]
|
self.__map = {} # key --> [key, prev, next]
|
||||||
dict.clear(self)
|
dict.clear(self)
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
if key not in self:
|
if key not in self:
|
||||||
end = self.__end
|
end = self.__end
|
||||||
curr = end[1]
|
curr = end[1]
|
||||||
curr[2] = end[1] = self.__map[key] = [key, curr, end]
|
curr[2] = end[1] = self.__map[key] = [key, curr, end]
|
||||||
dict.__setitem__(self, key, value)
|
dict.__setitem__(self, key, value)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
dict.__delitem__(self, key)
|
dict.__delitem__(self, key)
|
||||||
key, prev, next = self.__map.pop(key)
|
key, prev, next = self.__map.pop(key)
|
||||||
prev[2] = next
|
prev[2] = next
|
||||||
next[1] = prev
|
next[1] = prev
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
end = self.__end
|
end = self.__end
|
||||||
curr = end[2]
|
curr = end[2]
|
||||||
while curr is not end:
|
while curr is not end:
|
||||||
yield curr[0]
|
yield curr[0]
|
||||||
curr = curr[2]
|
curr = curr[2]
|
||||||
|
|
||||||
def __reversed__(self):
|
def __reversed__(self):
|
||||||
end = self.__end
|
end = self.__end
|
||||||
curr = end[1]
|
curr = end[1]
|
||||||
while curr is not end:
|
while curr is not end:
|
||||||
yield curr[0]
|
yield curr[0]
|
||||||
curr = curr[1]
|
curr = curr[1]
|
||||||
|
|
||||||
def popitem(self, last=True):
|
def popitem(self, last=True):
|
||||||
if not self:
|
if not self:
|
||||||
raise KeyError('dictionary is empty')
|
raise KeyError('dictionary is empty')
|
||||||
if last:
|
if last:
|
||||||
key = reversed(self).next()
|
key = reversed(self).next()
|
||||||
else:
|
else:
|
||||||
key = iter(self).next()
|
key = iter(self).next()
|
||||||
value = self.pop(key)
|
value = self.pop(key)
|
||||||
return key, value
|
return key, value
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
items = [[k, self[k]] for k in self]
|
items = [[k, self[k]] for k in self]
|
||||||
tmp = self.__map, self.__end
|
tmp = self.__map, self.__end
|
||||||
del self.__map, self.__end
|
del self.__map, self.__end
|
||||||
inst_dict = vars(self).copy()
|
inst_dict = vars(self).copy()
|
||||||
self.__map, self.__end = tmp
|
self.__map, self.__end = tmp
|
||||||
if inst_dict:
|
if inst_dict:
|
||||||
return (self.__class__, (items,), inst_dict)
|
return (self.__class__, (items,), inst_dict)
|
||||||
return self.__class__, (items,)
|
return self.__class__, (items,)
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return list(self)
|
return list(self)
|
||||||
|
|
||||||
setdefault = DictMixin.setdefault
|
setdefault = DictMixin.setdefault
|
||||||
update = DictMixin.update
|
update = DictMixin.update
|
||||||
pop = DictMixin.pop
|
pop = DictMixin.pop
|
||||||
values = DictMixin.values
|
values = DictMixin.values
|
||||||
items = DictMixin.items
|
items = DictMixin.items
|
||||||
iterkeys = DictMixin.iterkeys
|
iterkeys = DictMixin.iterkeys
|
||||||
itervalues = DictMixin.itervalues
|
itervalues = DictMixin.itervalues
|
||||||
iteritems = DictMixin.iteritems
|
iteritems = DictMixin.iteritems
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if not self:
|
if not self:
|
||||||
return '%s()' % (self.__class__.__name__,)
|
return '%s()' % (self.__class__.__name__,)
|
||||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return self.__class__(self)
|
return self.__class__(self)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromkeys(cls, iterable, value=None):
|
def fromkeys(cls, iterable, value=None):
|
||||||
d = cls()
|
d = cls()
|
||||||
for key in iterable:
|
for key in iterable:
|
||||||
d[key] = value
|
d[key] = value
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, OrderedDict):
|
if isinstance(other, OrderedDict):
|
||||||
if len(self) != len(other):
|
if len(self) != len(other):
|
||||||
return False
|
return False
|
||||||
for p, q in zip(self.items(), other.items()):
|
for p, q in zip(self.items(), other.items()):
|
||||||
if p != q:
|
if p != q:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
return dict.__eq__(self, other)
|
return dict.__eq__(self, other)
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self == other
|
return not self == other
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
"""
|
"""
|
||||||
Allows easy loading of pixmaps used in UI elements.
|
Allows easy loading of pixmaps used in UI elements.
|
||||||
Provides support for frozen environments as well.
|
Provides support for frozen environments as well.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os, sys, pickle
|
import os, sys, pickle
|
||||||
from ..functions import makeQImage
|
from ..functions import makeQImage
|
||||||
from ..Qt import QtGui
|
from ..Qt import QtGui
|
||||||
if sys.version_info[0] == 2:
|
if sys.version_info[0] == 2:
|
||||||
from . import pixmapData_2 as pixmapData
|
from . import pixmapData_2 as pixmapData
|
||||||
else:
|
else:
|
||||||
from . import pixmapData_3 as pixmapData
|
from . import pixmapData_3 as pixmapData
|
||||||
|
|
||||||
|
|
||||||
def getPixmap(name):
|
def getPixmap(name):
|
||||||
"""
|
"""
|
||||||
Return a QPixmap corresponding to the image file with the given name.
|
Return a QPixmap corresponding to the image file with the given name.
|
||||||
(eg. getPixmap('auto') loads pyqtgraph/pixmaps/auto.png)
|
(eg. getPixmap('auto') loads pyqtgraph/pixmaps/auto.png)
|
||||||
"""
|
"""
|
||||||
key = name+'.png'
|
key = name+'.png'
|
||||||
data = pixmapData.pixmapData[key]
|
data = pixmapData.pixmapData[key]
|
||||||
if isinstance(data, basestring) or isinstance(data, bytes):
|
if isinstance(data, basestring) or isinstance(data, bytes):
|
||||||
pixmapData.pixmapData[key] = pickle.loads(data)
|
pixmapData.pixmapData[key] = pickle.loads(data)
|
||||||
arr = pixmapData.pixmapData[key]
|
arr = pixmapData.pixmapData[key]
|
||||||
return QtGui.QPixmap(makeQImage(arr, alpha=True))
|
return QtGui.QPixmap(makeQImage(arr, alpha=True))
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtGui
|
||||||
import os, pickle, sys
|
import os, pickle, sys
|
||||||
|
|
||||||
path = os.path.abspath(os.path.split(__file__)[0])
|
path = os.path.abspath(os.path.split(__file__)[0])
|
||||||
pixmaps = {}
|
pixmaps = {}
|
||||||
for f in os.listdir(path):
|
for f in os.listdir(path):
|
||||||
if not f.endswith('.png'):
|
if not f.endswith('.png'):
|
||||||
continue
|
continue
|
||||||
print(f)
|
print(f)
|
||||||
img = QtGui.QImage(os.path.join(path, f))
|
img = QtGui.QImage(os.path.join(path, f))
|
||||||
ptr = img.bits()
|
ptr = img.bits()
|
||||||
ptr.setsize(img.byteCount())
|
ptr.setsize(img.byteCount())
|
||||||
arr = np.asarray(ptr).reshape(img.height(), img.width(), 4).transpose(1,0,2)
|
arr = np.asarray(ptr).reshape(img.height(), img.width(), 4).transpose(1,0,2)
|
||||||
pixmaps[f] = pickle.dumps(arr)
|
pixmaps[f] = pickle.dumps(arr)
|
||||||
ver = sys.version_info[0]
|
ver = sys.version_info[0]
|
||||||
fh = open(os.path.join(path, 'pixmapData_%d.py' %ver), 'w')
|
fh = open(os.path.join(path, 'pixmapData_%d.py' %ver), 'w')
|
||||||
fh.write("import numpy as np; pixmapData=%s" % repr(pixmaps))
|
fh.write("import numpy as np; pixmapData=%s" % repr(pixmaps))
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
21
setup.py
21
setup.py
@ -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
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,7 @@ for path, sd, files in os.walk('.'):
|
|||||||
py = os.path.join(path, base + '_pyqt.py')
|
py = os.path.join(path, base + '_pyqt.py')
|
||||||
if not os.path.exists(py) or os.stat(ui).st_mtime > os.stat(py).st_mtime:
|
if not os.path.exists(py) or os.stat(ui).st_mtime > os.stat(py).st_mtime:
|
||||||
os.system('%s %s > %s' % (pyqtuic, ui, py))
|
os.system('%s %s > %s' % (pyqtuic, ui, py))
|
||||||
print(py)
|
print(py)
|
||||||
|
|
||||||
py = os.path.join(path, base + '_pyside.py')
|
py = os.path.join(path, base + '_pyside.py')
|
||||||
if not os.path.exists(py) or os.stat(ui).st_mtime > os.stat(py).st_mtime:
|
if not os.path.exists(py) or os.stat(ui).st_mtime > os.stat(py).st_mtime:
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user