Merge branch 'ericdill-split-main' into develop
This commit is contained in:
commit
8285045422
3
.gitignore
vendored
3
.gitignore
vendored
@ -99,3 +99,6 @@ generated/
|
|||||||
MANIFEST
|
MANIFEST
|
||||||
deb_build
|
deb_build
|
||||||
rtr.cvs
|
rtr.cvs
|
||||||
|
|
||||||
|
# pytest parallel
|
||||||
|
.coverage*
|
||||||
|
@ -17,6 +17,10 @@ pyqtgraph-0.9.11 [unreleased]
|
|||||||
- Dock titles can be changed after creation
|
- Dock titles can be changed after creation
|
||||||
- Added Dock.sigClosed
|
- Added Dock.sigClosed
|
||||||
|
|
||||||
|
Maintenance:
|
||||||
|
- Add examples to unit tests
|
||||||
|
|
||||||
|
|
||||||
pyqtgraph-0.9.10
|
pyqtgraph-0.9.10
|
||||||
|
|
||||||
Fixed installation issues with more recent pip versions.
|
Fixed installation issues with more recent pip versions.
|
||||||
|
@ -49,3 +49,12 @@ Please use the following guidelines when preparing changes:
|
|||||||
|
|
||||||
QObject subclasses that implement new signals should also describe
|
QObject subclasses that implement new signals should also describe
|
||||||
these in a similar table.
|
these in a similar table.
|
||||||
|
|
||||||
|
* Setting up a test environment.
|
||||||
|
|
||||||
|
Tests for a module should ideally cover all code in that module,
|
||||||
|
i.e., statement coverage should be at 100%.
|
||||||
|
|
||||||
|
To measure the test coverage, install py.test, pytest-cov and pytest-xdist.
|
||||||
|
Then run 'py.test --cov -n 4' to run the test suite with coverage on 4 cores.
|
||||||
|
|
||||||
|
@ -1,14 +1,121 @@
|
|||||||
import sys, os
|
import sys, os
|
||||||
import pyqtgraph as pg
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__" and (__package__ is None or __package__==''):
|
if __name__ == "__main__" and (__package__ is None or __package__==''):
|
||||||
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
sys.path.insert(0, parent_dir)
|
sys.path.insert(0, parent_dir)
|
||||||
import examples
|
import examples
|
||||||
__package__ = "examples"
|
__package__ = "examples"
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import subprocess
|
||||||
|
from pyqtgraph.python2_3 import basestring
|
||||||
|
from pyqtgraph.Qt import QtGui, USE_PYSIDE, USE_PYQT5
|
||||||
|
|
||||||
from .utils import buildFileList, testFile, run, path, examples
|
|
||||||
|
from .utils import buildFileList, testFile, path, examples
|
||||||
|
|
||||||
|
if USE_PYSIDE:
|
||||||
|
from .exampleLoaderTemplate_pyside import Ui_Form
|
||||||
|
elif USE_PYQT5:
|
||||||
|
from .exampleLoaderTemplate_pyqt5 import Ui_Form
|
||||||
|
else:
|
||||||
|
from .exampleLoaderTemplate_pyqt import Ui_Form
|
||||||
|
|
||||||
|
class ExampleLoader(QtGui.QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
QtGui.QMainWindow.__init__(self)
|
||||||
|
self.ui = Ui_Form()
|
||||||
|
self.cw = QtGui.QWidget()
|
||||||
|
self.setCentralWidget(self.cw)
|
||||||
|
self.ui.setupUi(self.cw)
|
||||||
|
|
||||||
|
self.codeBtn = QtGui.QPushButton('Run Edited Code')
|
||||||
|
self.codeLayout = QtGui.QGridLayout()
|
||||||
|
self.ui.codeView.setLayout(self.codeLayout)
|
||||||
|
self.codeLayout.addItem(QtGui.QSpacerItem(100,100,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding), 0, 0)
|
||||||
|
self.codeLayout.addWidget(self.codeBtn, 1, 1)
|
||||||
|
self.codeBtn.hide()
|
||||||
|
|
||||||
|
global examples
|
||||||
|
self.itemCache = []
|
||||||
|
self.populateTree(self.ui.exampleTree.invisibleRootItem(), examples)
|
||||||
|
self.ui.exampleTree.expandAll()
|
||||||
|
|
||||||
|
self.resize(1000,500)
|
||||||
|
self.show()
|
||||||
|
self.ui.splitter.setSizes([250,750])
|
||||||
|
self.ui.loadBtn.clicked.connect(self.loadFile)
|
||||||
|
self.ui.exampleTree.currentItemChanged.connect(self.showFile)
|
||||||
|
self.ui.exampleTree.itemDoubleClicked.connect(self.loadFile)
|
||||||
|
self.ui.codeView.textChanged.connect(self.codeEdited)
|
||||||
|
self.codeBtn.clicked.connect(self.runEditedCode)
|
||||||
|
|
||||||
|
def populateTree(self, root, examples):
|
||||||
|
for key, val in examples.items():
|
||||||
|
item = QtGui.QTreeWidgetItem([key])
|
||||||
|
self.itemCache.append(item) # PyQt 4.9.6 no longer keeps references to these wrappers,
|
||||||
|
# so we need to make an explicit reference or else the .file
|
||||||
|
# attribute will disappear.
|
||||||
|
if isinstance(val, basestring):
|
||||||
|
item.file = val
|
||||||
|
else:
|
||||||
|
self.populateTree(item, val)
|
||||||
|
root.addChild(item)
|
||||||
|
|
||||||
|
def currentFile(self):
|
||||||
|
item = self.ui.exampleTree.currentItem()
|
||||||
|
if hasattr(item, 'file'):
|
||||||
|
global path
|
||||||
|
return os.path.join(path, item.file)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def loadFile(self, edited=False):
|
||||||
|
|
||||||
|
extra = []
|
||||||
|
qtLib = str(self.ui.qtLibCombo.currentText())
|
||||||
|
gfxSys = str(self.ui.graphicsSystemCombo.currentText())
|
||||||
|
|
||||||
|
if qtLib != 'default':
|
||||||
|
extra.append(qtLib.lower())
|
||||||
|
elif gfxSys != 'default':
|
||||||
|
extra.append(gfxSys)
|
||||||
|
|
||||||
|
if edited:
|
||||||
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
proc = subprocess.Popen([sys.executable, '-'] + extra, stdin=subprocess.PIPE, cwd=path)
|
||||||
|
code = str(self.ui.codeView.toPlainText()).encode('UTF-8')
|
||||||
|
proc.stdin.write(code)
|
||||||
|
proc.stdin.close()
|
||||||
|
else:
|
||||||
|
fn = self.currentFile()
|
||||||
|
if fn is None:
|
||||||
|
return
|
||||||
|
if sys.platform.startswith('win'):
|
||||||
|
os.spawnl(os.P_NOWAIT, sys.executable, '"'+sys.executable+'"', '"' + fn + '"', *extra)
|
||||||
|
else:
|
||||||
|
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, fn, *extra)
|
||||||
|
|
||||||
|
def showFile(self):
|
||||||
|
fn = self.currentFile()
|
||||||
|
if fn is None:
|
||||||
|
self.ui.codeView.clear()
|
||||||
|
return
|
||||||
|
if os.path.isdir(fn):
|
||||||
|
fn = os.path.join(fn, '__main__.py')
|
||||||
|
text = open(fn).read()
|
||||||
|
self.ui.codeView.setPlainText(text)
|
||||||
|
self.ui.loadedFileLabel.setText(fn)
|
||||||
|
self.codeBtn.hide()
|
||||||
|
|
||||||
|
def codeEdited(self):
|
||||||
|
self.codeBtn.show()
|
||||||
|
|
||||||
|
def runEditedCode(self):
|
||||||
|
self.loadFile(edited=True)
|
||||||
|
|
||||||
|
def run():
|
||||||
|
app = QtGui.QApplication([])
|
||||||
|
loader = ExampleLoader()
|
||||||
|
|
||||||
|
app.exec_()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
@ -1,14 +1,32 @@
|
|||||||
from __future__ import print_function, division, absolute_import
|
from __future__ import print_function, division, absolute_import
|
||||||
from pyqtgraph import Qt
|
from pyqtgraph import Qt
|
||||||
from . import utils
|
from examples import utils
|
||||||
|
import importlib
|
||||||
|
import itertools
|
||||||
|
import pytest
|
||||||
|
|
||||||
files = utils.buildFileList(utils.examples)
|
files = utils.buildFileList(utils.examples)
|
||||||
|
|
||||||
import pytest
|
frontends = {Qt.PYQT4: False, Qt.PYSIDE: False}
|
||||||
|
# frontends = {Qt.PYQT4: False, Qt.PYQT5: False, Qt.PYSIDE: False}
|
||||||
|
|
||||||
|
# sort out which of the front ends are available
|
||||||
|
for frontend in frontends.keys():
|
||||||
|
try:
|
||||||
|
importlib.import_module(frontend)
|
||||||
|
frontends[frontend] = True
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
@pytest.mark.parametrize("f", files)
|
@pytest.mark.parametrize(
|
||||||
def test_examples(f):
|
"frontend, f", itertools.product(sorted(list(frontends.keys())), files))
|
||||||
|
def test_examples(frontend, f):
|
||||||
# Test the examples with whatever the current QT_LIB front
|
# Test the examples with whatever the current QT_LIB front
|
||||||
# end is
|
# end is
|
||||||
utils.testFile(f[0], f[1], utils.sys.executable, Qt.QT_LIB)
|
print('frontend = %s. f = %s' % (frontend, f))
|
||||||
|
if not frontends[frontend]:
|
||||||
|
pytest.skip('{} is not installed. Skipping tests'.format(frontend))
|
||||||
|
utils.testFile(f[0], f[1], utils.sys.executable, frontend)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pytest.cmdline.main()
|
||||||
|
@ -4,17 +4,8 @@ import time
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pyqtgraph.pgcollections import OrderedDict
|
from pyqtgraph.pgcollections import OrderedDict
|
||||||
from pyqtgraph.Qt import QtGui, USE_PYSIDE, USE_PYQT5
|
|
||||||
from pyqtgraph.python2_3 import basestring
|
from pyqtgraph.python2_3 import basestring
|
||||||
|
|
||||||
if USE_PYSIDE:
|
|
||||||
from .exampleLoaderTemplate_pyside import Ui_Form
|
|
||||||
elif USE_PYQT5:
|
|
||||||
from .exampleLoaderTemplate_pyqt5 import Ui_Form
|
|
||||||
else:
|
|
||||||
from .exampleLoaderTemplate_pyqt import Ui_Form
|
|
||||||
|
|
||||||
|
|
||||||
path = os.path.abspath(os.path.dirname(__file__))
|
path = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
@ -96,103 +87,6 @@ examples = OrderedDict([
|
|||||||
('Custom Flowchart Nodes', 'FlowchartCustomNode.py'),
|
('Custom Flowchart Nodes', 'FlowchartCustomNode.py'),
|
||||||
])
|
])
|
||||||
|
|
||||||
class ExampleLoader(QtGui.QMainWindow):
|
|
||||||
def __init__(self):
|
|
||||||
QtGui.QMainWindow.__init__(self)
|
|
||||||
self.ui = Ui_Form()
|
|
||||||
self.cw = QtGui.QWidget()
|
|
||||||
self.setCentralWidget(self.cw)
|
|
||||||
self.ui.setupUi(self.cw)
|
|
||||||
|
|
||||||
self.codeBtn = QtGui.QPushButton('Run Edited Code')
|
|
||||||
self.codeLayout = QtGui.QGridLayout()
|
|
||||||
self.ui.codeView.setLayout(self.codeLayout)
|
|
||||||
self.codeLayout.addItem(QtGui.QSpacerItem(100,100,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding), 0, 0)
|
|
||||||
self.codeLayout.addWidget(self.codeBtn, 1, 1)
|
|
||||||
self.codeBtn.hide()
|
|
||||||
|
|
||||||
global examples
|
|
||||||
self.itemCache = []
|
|
||||||
self.populateTree(self.ui.exampleTree.invisibleRootItem(), examples)
|
|
||||||
self.ui.exampleTree.expandAll()
|
|
||||||
|
|
||||||
self.resize(1000,500)
|
|
||||||
self.show()
|
|
||||||
self.ui.splitter.setSizes([250,750])
|
|
||||||
self.ui.loadBtn.clicked.connect(self.loadFile)
|
|
||||||
self.ui.exampleTree.currentItemChanged.connect(self.showFile)
|
|
||||||
self.ui.exampleTree.itemDoubleClicked.connect(self.loadFile)
|
|
||||||
self.ui.codeView.textChanged.connect(self.codeEdited)
|
|
||||||
self.codeBtn.clicked.connect(self.runEditedCode)
|
|
||||||
|
|
||||||
def populateTree(self, root, examples):
|
|
||||||
for key, val in examples.items():
|
|
||||||
item = QtGui.QTreeWidgetItem([key])
|
|
||||||
self.itemCache.append(item) # PyQt 4.9.6 no longer keeps references to these wrappers,
|
|
||||||
# so we need to make an explicit reference or else the .file
|
|
||||||
# attribute will disappear.
|
|
||||||
if isinstance(val, basestring):
|
|
||||||
item.file = val
|
|
||||||
else:
|
|
||||||
self.populateTree(item, val)
|
|
||||||
root.addChild(item)
|
|
||||||
|
|
||||||
def currentFile(self):
|
|
||||||
item = self.ui.exampleTree.currentItem()
|
|
||||||
if hasattr(item, 'file'):
|
|
||||||
global path
|
|
||||||
return os.path.join(path, item.file)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def loadFile(self, edited=False):
|
|
||||||
|
|
||||||
extra = []
|
|
||||||
qtLib = str(self.ui.qtLibCombo.currentText())
|
|
||||||
gfxSys = str(self.ui.graphicsSystemCombo.currentText())
|
|
||||||
|
|
||||||
if qtLib != 'default':
|
|
||||||
extra.append(qtLib.lower())
|
|
||||||
elif gfxSys != 'default':
|
|
||||||
extra.append(gfxSys)
|
|
||||||
|
|
||||||
if edited:
|
|
||||||
path = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
proc = subprocess.Popen([sys.executable, '-'] + extra, stdin=subprocess.PIPE, cwd=path)
|
|
||||||
code = str(self.ui.codeView.toPlainText()).encode('UTF-8')
|
|
||||||
proc.stdin.write(code)
|
|
||||||
proc.stdin.close()
|
|
||||||
else:
|
|
||||||
fn = self.currentFile()
|
|
||||||
if fn is None:
|
|
||||||
return
|
|
||||||
if sys.platform.startswith('win'):
|
|
||||||
os.spawnl(os.P_NOWAIT, sys.executable, '"'+sys.executable+'"', '"' + fn + '"', *extra)
|
|
||||||
else:
|
|
||||||
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, fn, *extra)
|
|
||||||
|
|
||||||
def showFile(self):
|
|
||||||
fn = self.currentFile()
|
|
||||||
if fn is None:
|
|
||||||
self.ui.codeView.clear()
|
|
||||||
return
|
|
||||||
if os.path.isdir(fn):
|
|
||||||
fn = os.path.join(fn, '__main__.py')
|
|
||||||
text = open(fn).read()
|
|
||||||
self.ui.codeView.setPlainText(text)
|
|
||||||
self.ui.loadedFileLabel.setText(fn)
|
|
||||||
self.codeBtn.hide()
|
|
||||||
|
|
||||||
def codeEdited(self):
|
|
||||||
self.codeBtn.show()
|
|
||||||
|
|
||||||
def runEditedCode(self):
|
|
||||||
self.loadFile(edited=True)
|
|
||||||
|
|
||||||
def run():
|
|
||||||
app = QtGui.QApplication([])
|
|
||||||
loader = ExampleLoader()
|
|
||||||
|
|
||||||
app.exec_()
|
|
||||||
|
|
||||||
def buildFileList(examples, files=None):
|
def buildFileList(examples, files=None):
|
||||||
if files == None:
|
if files == None:
|
||||||
|
@ -523,6 +523,10 @@ class PlotDataItem(GraphicsObject):
|
|||||||
#y = y[::ds]
|
#y = y[::ds]
|
||||||
if self.opts['fftMode']:
|
if self.opts['fftMode']:
|
||||||
x,y = self._fourierTransform(x, y)
|
x,y = self._fourierTransform(x, y)
|
||||||
|
# Ignore the first bin for fft data if we have a logx scale
|
||||||
|
if self.opts['logMode'][0]:
|
||||||
|
x=x[1:]
|
||||||
|
y=y[1:]
|
||||||
if self.opts['logMode'][0]:
|
if self.opts['logMode'][0]:
|
||||||
x = np.log10(x)
|
x = np.log10(x)
|
||||||
if self.opts['logMode'][1]:
|
if self.opts['logMode'][1]:
|
||||||
|
Loading…
Reference in New Issue
Block a user