Merge pull request #1846 from pijyoi/import_hygiene
reduce pollution of pg namespace
This commit is contained in:
commit
93fa8664cb
0
pyqtgraph/Qt/QtCore/__init__.py
Normal file
0
pyqtgraph/Qt/QtCore/__init__.py
Normal file
0
pyqtgraph/Qt/QtGui/__init__.py
Normal file
0
pyqtgraph/Qt/QtGui/__init__.py
Normal file
0
pyqtgraph/Qt/QtWidgets/__init__.py
Normal file
0
pyqtgraph/Qt/QtWidgets/__init__.py
Normal file
@ -12,7 +12,7 @@ This module exists to smooth out some of the differences between PySide and PyQt
|
||||
|
||||
import os, sys, re, time, subprocess, warnings
|
||||
|
||||
from .python2_3 import asUnicode
|
||||
from ..python2_3 import asUnicode
|
||||
|
||||
PYSIDE = 'PySide'
|
||||
PYSIDE2 = 'PySide2'
|
||||
@ -130,10 +130,29 @@ def _loadUiType(uiFile):
|
||||
return form_class, base_class
|
||||
|
||||
|
||||
# For historical reasons, pyqtgraph maintains a Qt4-ish interface back when
|
||||
# there wasn't a QtWidgets module. This _was_ done by monkey-patching all of
|
||||
# QtWidgets into the QtGui module. This monkey-patching modifies QtGui at a
|
||||
# global level.
|
||||
# To avoid this, we now maintain a local "mirror" of QtCore, QtGui and QtWidgets.
|
||||
# Thus, when monkey-patching happens later on in this file, they will only affect
|
||||
# the local modules and not the global modules.
|
||||
def _copy_attrs(src, dst):
|
||||
for o in dir(src):
|
||||
if not hasattr(dst, o):
|
||||
setattr(dst, o, getattr(src, o))
|
||||
|
||||
from . import QtCore, QtGui, QtWidgets
|
||||
|
||||
if QT_LIB == PYQT5:
|
||||
# We're using PyQt5 which has a different structure so we're going to use a shim to
|
||||
# recreate the Qt4 structure for Qt5
|
||||
from PyQt5 import QtGui, QtCore, QtWidgets, sip, uic
|
||||
import PyQt5.QtCore, PyQt5.QtGui, PyQt5.QtWidgets
|
||||
_copy_attrs(PyQt5.QtCore, QtCore)
|
||||
_copy_attrs(PyQt5.QtGui, QtGui)
|
||||
_copy_attrs(PyQt5.QtWidgets, QtWidgets)
|
||||
|
||||
from PyQt5 import sip, uic
|
||||
|
||||
try:
|
||||
from PyQt5 import QtSvg
|
||||
@ -147,7 +166,12 @@ if QT_LIB == PYQT5:
|
||||
VERSION_INFO = 'PyQt5 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
|
||||
|
||||
elif QT_LIB == PYQT6:
|
||||
from PyQt6 import QtGui, QtCore, QtWidgets, sip, uic
|
||||
import PyQt6.QtCore, PyQt6.QtGui, PyQt6.QtWidgets
|
||||
_copy_attrs(PyQt6.QtCore, QtCore)
|
||||
_copy_attrs(PyQt6.QtGui, QtGui)
|
||||
_copy_attrs(PyQt6.QtWidgets, QtWidgets)
|
||||
|
||||
from PyQt6 import sip, uic
|
||||
|
||||
try:
|
||||
from PyQt6 import QtSvg
|
||||
@ -165,7 +189,10 @@ elif QT_LIB == PYQT6:
|
||||
VERSION_INFO = 'PyQt6 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
|
||||
|
||||
elif QT_LIB == PYSIDE2:
|
||||
from PySide2 import QtGui, QtCore, QtWidgets
|
||||
import PySide2.QtCore, PySide2.QtGui, PySide2.QtWidgets
|
||||
_copy_attrs(PySide2.QtCore, QtCore)
|
||||
_copy_attrs(PySide2.QtGui, QtGui)
|
||||
_copy_attrs(PySide2.QtWidgets, QtWidgets)
|
||||
|
||||
try:
|
||||
from PySide2 import QtSvg
|
||||
@ -182,7 +209,10 @@ elif QT_LIB == PYSIDE2:
|
||||
VERSION_INFO = 'PySide2 ' + PySide2.__version__ + ' Qt ' + QtCore.__version__
|
||||
|
||||
elif QT_LIB == PYSIDE6:
|
||||
from PySide6 import QtGui, QtCore, QtWidgets
|
||||
import PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets
|
||||
_copy_attrs(PySide6.QtCore, QtCore)
|
||||
_copy_attrs(PySide6.QtGui, QtGui)
|
||||
_copy_attrs(PySide6.QtWidgets, QtWidgets)
|
||||
|
||||
try:
|
||||
from PySide6 import QtSvg
|
@ -1,6 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from .Qt import QtCore, QtGui
|
||||
|
||||
__all__ = ['ThreadsafeTimer']
|
||||
|
||||
class ThreadsafeTimer(QtCore.QObject):
|
||||
"""
|
||||
Thread-safe replacement for QTimer.
|
||||
|
@ -10,7 +10,7 @@ __version__ = '0.12.1'
|
||||
|
||||
## 'Qt' is a local module; it is intended mainly to cover up the differences
|
||||
## between PyQt4 and PySide.
|
||||
from .Qt import QtGui, mkQApp
|
||||
from .Qt import QtCore, QtGui, mkQApp
|
||||
from .Qt import exec_ as exec
|
||||
|
||||
## not really safe--If we accidentally create another QApplication, the process hangs (and it is very difficult to trace the cause)
|
||||
@ -280,6 +280,15 @@ from .ptime import time
|
||||
from .Qt import isQObjectAlive
|
||||
from .ThreadsafeTimer import *
|
||||
|
||||
# indirect imports used within library
|
||||
from .GraphicsScene import GraphicsScene
|
||||
from .python2_3 import asUnicode
|
||||
from .util.cupy_helper import getCupy
|
||||
|
||||
# indirect imports known to be used outside of the library
|
||||
from .metaarray import MetaArray
|
||||
from .ordereddict import OrderedDict
|
||||
|
||||
|
||||
##############################################################
|
||||
## PyQt and PySide both are prone to crashing on exit.
|
||||
|
@ -26,6 +26,31 @@ from .metaarray import MetaArray
|
||||
from collections import OrderedDict
|
||||
from .python2_3 import asUnicode, basestring
|
||||
|
||||
# in order of appearance in this file.
|
||||
# add new functions to this list only if they are to reside in pg namespace.
|
||||
__all__ = [
|
||||
'siScale', 'siFormat', 'siParse', 'siEval', 'siApply',
|
||||
'Color', 'mkColor', 'mkBrush', 'mkPen', 'hsvColor',
|
||||
'CIELabColor', 'colorCIELab', 'colorDistance',
|
||||
'colorTuple', 'colorStr', 'intColor', 'glColor',
|
||||
'makeArrowPath', 'eq',
|
||||
'affineSliceCoords', 'affineSlice',
|
||||
'interweaveArrays', 'interpolateArray', 'subArray',
|
||||
'transformToArray', 'transformCoordinates',
|
||||
'solve3DTransform', 'solveBilinearTransform',
|
||||
'clip_scalar', 'clip_array', 'rescaleData', 'applyLookupTable',
|
||||
'makeRGBA', 'makeARGB',
|
||||
# 'try_fastpath_argb', 'ndarray_to_qimage',
|
||||
'makeQImage',
|
||||
# 'qimage_to_ndarray',
|
||||
'imageToArray', 'colorToAlpha',
|
||||
'gaussianFilter', 'downsample', 'arrayToQPath',
|
||||
# 'ndarray_from_qpolygonf', 'create_qpolygonf', 'arrayToQPolygonF',
|
||||
'isocurve', 'traceImage', 'isosurface',
|
||||
'invertQTransform',
|
||||
'pseudoScatter', 'toposort', 'disconnect', 'SignalBlock']
|
||||
|
||||
|
||||
Colors = {
|
||||
'b': QtGui.QColor(0,0,255,255),
|
||||
'g': QtGui.QColor(0,255,0,255),
|
||||
|
@ -3,6 +3,8 @@ from .. import functions as fn
|
||||
from .PlotDataItem import PlotDataItem
|
||||
from .PlotCurveItem import PlotCurveItem
|
||||
|
||||
__all__ = ['FillBetweenItem']
|
||||
|
||||
class FillBetweenItem(QtGui.QGraphicsPathItem):
|
||||
"""
|
||||
GraphicsItem filling the space between two PlotDataItems.
|
||||
|
@ -9,6 +9,7 @@ from .. import functions as fn
|
||||
import weakref
|
||||
import operator
|
||||
|
||||
__all__ = ['GraphicsItem']
|
||||
|
||||
# Recipe from https://docs.python.org/3.8/library/collections.html#collections.OrderedDict
|
||||
# slightly adapted for Python 3.7 compatibility
|
||||
|
@ -1,6 +1,7 @@
|
||||
from ..Qt import QtGui, QtCore
|
||||
from ..Point import Point
|
||||
|
||||
__all__ = ['GraphicsWidgetAnchor']
|
||||
|
||||
class GraphicsWidgetAnchor(object):
|
||||
"""
|
||||
|
@ -12,6 +12,7 @@ from .ViewBox import *
|
||||
from .GradientEditorItem import *
|
||||
from .LinearRegionItem import *
|
||||
from .PlotDataItem import *
|
||||
from .PlotCurveItem import *
|
||||
from .AxisItem import *
|
||||
from .GridItem import *
|
||||
from ..Point import Point
|
||||
|
@ -3,6 +3,7 @@ from .GraphicsObject import *
|
||||
from .. import functions as fn
|
||||
from ..Qt import QtGui, QtCore
|
||||
|
||||
__all__ = ['IsocurveItem']
|
||||
|
||||
class IsocurveItem(GraphicsObject):
|
||||
"""
|
||||
|
@ -6,6 +6,7 @@ from .GraphicsObject import GraphicsObject
|
||||
from .. import mkBrush, mkPen
|
||||
from .. import functions as fn
|
||||
|
||||
__all__ = ['NonUniformImage']
|
||||
|
||||
class NonUniformImage(GraphicsObject):
|
||||
"""
|
||||
|
@ -11,6 +11,7 @@ from .. import functions as fn
|
||||
from .. import debug as debug
|
||||
from .. import getConfigOption
|
||||
|
||||
__all__ = ['PlotDataItem']
|
||||
|
||||
class PlotDataItem(GraphicsObject):
|
||||
"""
|
||||
|
@ -14,9 +14,11 @@ from ..InfiniteLine import InfiniteLine
|
||||
from ..LabelItem import LabelItem
|
||||
from ..LegendItem import LegendItem
|
||||
from ..PlotDataItem import PlotDataItem
|
||||
from ..PlotCurveItem import PlotCurveItem
|
||||
from ..ScatterPlotItem import ScatterPlotItem
|
||||
from ..ViewBox import ViewBox
|
||||
from ... import functions as fn
|
||||
from ... import icons, PlotCurveItem, ScatterPlotItem
|
||||
from ... import icons
|
||||
from ...Qt import QtGui, QtCore, QT_LIB
|
||||
from ...WidgetGroup import WidgetGroup
|
||||
from ...python2_3 import basestring
|
||||
|
@ -1 +1,3 @@
|
||||
from .PlotItem import PlotItem
|
||||
|
||||
__all__ = ['PlotItem']
|
||||
|
@ -10,6 +10,7 @@ from .ViewBox import ViewBox
|
||||
import string
|
||||
import warnings
|
||||
|
||||
__all__ = ['TargetItem', 'TargetLabel']
|
||||
|
||||
class TargetItem(UIGraphicsItem):
|
||||
"""Draws a draggable target symbol (circle plus crosshair).
|
||||
|
@ -4,6 +4,7 @@ from ..Point import Point
|
||||
from .. import functions as fn
|
||||
from .GraphicsObject import GraphicsObject
|
||||
|
||||
__all__ = ['TextItem']
|
||||
|
||||
class TextItem(GraphicsObject):
|
||||
"""
|
||||
|
@ -1 +1,3 @@
|
||||
from .ViewBox import ViewBox
|
||||
|
||||
__all__ = ['ViewBox']
|
||||
|
@ -6,6 +6,8 @@ it is possible to place any widget into its own window by simply calling its
|
||||
show() method.
|
||||
"""
|
||||
|
||||
__all__ = ['GraphicsWindow', 'TabWindow', 'PlotWindow', 'ImageWindow']
|
||||
|
||||
from .Qt import QtCore, QtGui, mkQApp
|
||||
from .widgets.PlotWidget import *
|
||||
from .imageview import *
|
||||
|
@ -4,3 +4,5 @@ Includes ROI plotting over time and image normalization.
|
||||
"""
|
||||
|
||||
from .ImageView import ImageView
|
||||
|
||||
__all__ = ['ImageView']
|
@ -1,137 +1,12 @@
|
||||
# Copyright (c) 2009 Raymond Hettinger
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import collections
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"OrderedDict is in the standard library for supported versions of Python. Will be removed in 0.13",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
|
||||
import sys
|
||||
if sys.version[0] > '2':
|
||||
from collections import OrderedDict
|
||||
else:
|
||||
from UserDict import DictMixin
|
||||
|
||||
class OrderedDict(dict, DictMixin):
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__end
|
||||
except AttributeError:
|
||||
self.clear()
|
||||
self.update(*args, **kwds)
|
||||
|
||||
def clear(self):
|
||||
self.__end = end = []
|
||||
end += [None, end, end] # sentinel node for doubly linked list
|
||||
self.__map = {} # key --> [key, prev, next]
|
||||
dict.clear(self)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key not in self:
|
||||
end = self.__end
|
||||
curr = end[1]
|
||||
curr[2] = end[1] = self.__map[key] = [key, curr, end]
|
||||
dict.__setitem__(self, key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
dict.__delitem__(self, key)
|
||||
key, prev, next = self.__map.pop(key)
|
||||
prev[2] = next
|
||||
next[1] = prev
|
||||
|
||||
def __iter__(self):
|
||||
end = self.__end
|
||||
curr = end[2]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[2]
|
||||
|
||||
def __reversed__(self):
|
||||
end = self.__end
|
||||
curr = end[1]
|
||||
while curr is not end:
|
||||
yield curr[0]
|
||||
curr = curr[1]
|
||||
|
||||
def popitem(self, last=True):
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
if last:
|
||||
key = reversed(self).next()
|
||||
else:
|
||||
key = iter(self).next()
|
||||
value = self.pop(key)
|
||||
return key, value
|
||||
|
||||
def __reduce__(self):
|
||||
items = [[k, self[k]] for k in self]
|
||||
tmp = self.__map, self.__end
|
||||
del self.__map, self.__end
|
||||
inst_dict = vars(self).copy()
|
||||
self.__map, self.__end = tmp
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def keys(self):
|
||||
return list(self)
|
||||
|
||||
setdefault = DictMixin.setdefault
|
||||
update = DictMixin.update
|
||||
pop = DictMixin.pop
|
||||
values = DictMixin.values
|
||||
items = DictMixin.items
|
||||
iterkeys = DictMixin.iterkeys
|
||||
itervalues = DictMixin.itervalues
|
||||
iteritems = DictMixin.iteritems
|
||||
|
||||
def __repr__(self):
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
|
||||
def copy(self):
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
d = cls()
|
||||
for key in iterable:
|
||||
d[key] = value
|
||||
return d
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, OrderedDict):
|
||||
if len(self) != len(other):
|
||||
return False
|
||||
for p, q in zip(self.items(), other.items()):
|
||||
if p != q:
|
||||
return False
|
||||
return True
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
class OrderedDict(collections.OrderedDict):
|
||||
def __init__(self, *args, **kwds):
|
||||
warnings.warn(
|
||||
"OrderedDict is in the standard library for supported versions of Python. Will be removed in 0.13",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
super().__init__(*args, **kwds)
|
@ -4,6 +4,7 @@ from ..SignalProxy import SignalProxy
|
||||
from collections import OrderedDict
|
||||
from ..python2_3 import asUnicode, basestring
|
||||
|
||||
__all__ = ['ComboBox']
|
||||
|
||||
class ComboBox(QtGui.QComboBox):
|
||||
"""Extends QComboBox to add extra functionality.
|
||||
|
@ -2,6 +2,7 @@ from ..Qt import QtGui, QtCore
|
||||
from .PathButton import PathButton
|
||||
from ..python2_3 import basestring
|
||||
|
||||
__all__ = ['GroupBox']
|
||||
|
||||
class GroupBox(QtGui.QGroupBox):
|
||||
"""Subclass of QGroupBox that implements collapse handle.
|
||||
|
@ -6,6 +6,8 @@ from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Navigatio
|
||||
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
__all__ = ['MatplotlibWidget']
|
||||
|
||||
class MatplotlibWidget(QtGui.QWidget):
|
||||
"""
|
||||
Implements a Matplotlib figure inside a QWidget.
|
||||
|
@ -18,6 +18,7 @@ except (ImportError, AttributeError):
|
||||
# AttributeError upon import
|
||||
HAVE_OPENGL = False
|
||||
|
||||
__all__ = ['RawImageWidget']
|
||||
|
||||
class RawImageWidget(QtGui.QWidget):
|
||||
"""
|
||||
@ -78,6 +79,7 @@ class RawImageWidget(QtGui.QWidget):
|
||||
|
||||
|
||||
if HAVE_OPENGL:
|
||||
__all__.append('RawImageGLWidget')
|
||||
class RawImageGLWidget(QOpenGLWidget):
|
||||
"""
|
||||
Similar to RawImageWidget, but uses a GL widget to do all drawing.
|
||||
|
@ -2,6 +2,7 @@
|
||||
CSV export test
|
||||
"""
|
||||
from __future__ import division, print_function, absolute_import
|
||||
import numpy as np
|
||||
import pyqtgraph as pg
|
||||
import csv
|
||||
import tempfile
|
||||
@ -19,11 +20,11 @@ def test_CSVExporter():
|
||||
plt.plot(y=y1, name='myPlot')
|
||||
|
||||
y2 = [3,4,6,1,2,4,2,3,5,3,5,1,3]
|
||||
x2 = pg.np.linspace(0, 1.0, len(y2))
|
||||
x2 = np.linspace(0, 1.0, len(y2))
|
||||
plt.plot(x=x2, y=y2)
|
||||
|
||||
y3 = [1,5,2,3,4,6,1,2,4,2,3,5,3]
|
||||
x3 = pg.np.linspace(0, 1.0, len(y3)+1)
|
||||
x3 = np.linspace(0, 1.0, len(y3)+1)
|
||||
plt.plot(x=x3, y=y3, stepMode="center")
|
||||
|
||||
ex = pg.exporters.CSVExporter(plt.plotItem)
|
||||
|
@ -7,7 +7,7 @@ pytest.importorskip("matplotlib")
|
||||
app = pg.mkQApp()
|
||||
|
||||
skip_qt6 = pytest.mark.skipif(
|
||||
pg.QT_LIB in ["PySide6", "PyQt6"],
|
||||
pg.Qt.QT_LIB in ["PySide6", "PyQt6"],
|
||||
reason= (
|
||||
"Matplotlib has no Qt6 support yet, "
|
||||
"see https://github.com/matplotlib/matplotlib/pull/19255"
|
||||
|
@ -229,7 +229,7 @@ def test_setRect():
|
||||
|
||||
|
||||
def test_dividebyzero():
|
||||
im = pg.image(pg.np.random.normal(size=(100,100)))
|
||||
im = pg.image(np.random.normal(size=(100,100)))
|
||||
im.imageItem.setAutoDownsample(True)
|
||||
im.view.setRange(xRange=[-5+25, 5e+25],yRange=[-5e+25, 5e+25])
|
||||
app.processEvents()
|
||||
|
@ -37,7 +37,7 @@ def test_PlotWidget():
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
w = pg.PlotWidget(*args, **kwds)
|
||||
data = pg.np.array([1,5,2,4,3])
|
||||
data = np.array([1,5,2,4,3])
|
||||
c = w.plot(data, name='stuff')
|
||||
w.addLegend()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user