Skip to content

Commit 0449fff

Browse files
committed
Fix cyclic import issue in plotpy.tools module
1 parent c751200 commit 0449fff

File tree

11 files changed

+94
-47
lines changed

11 files changed

+94
-47
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog #
22

3+
## Version 2.4.3 ##
4+
5+
In this release, test coverage is 79%.
6+
7+
🛠️ Bug fixes:
8+
9+
* Fix cyclic import in `plotpy.tools` module:
10+
* Some tools in `plotpy.tools` subpackage were importing the `plotpy.plot` module,
11+
which was importing the `plotpy.tools` module, causing a cyclic import issue
12+
* This is now fixed by introducing new constants for axis IDs in the
13+
`plotpy.constants` module, and using them everywhere in the code, thus avoiding
14+
to import the `plotpy.plot` module just to get the axis IDs
15+
316
## Version 2.4.2 ##
417

518
In this release, test coverage is 79%.

plotpy/constants.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616

1717
from plotpy.config import _
1818

19+
# ===============================================================================
20+
# Plot axes
21+
# ===============================================================================
22+
23+
#: ID of the x axis
24+
AXIS_IDS = Y_LEFT, Y_RIGHT, X_BOTTOM, X_TOP = range(4)
25+
26+
1927
# ===============================================================================
2028
# Plot types
2129
# ===============================================================================

plotpy/items/image/misc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
from plotpy import io
1515
from plotpy.config import _
16+
from plotpy.constants import X_BOTTOM, Y_LEFT
1617
from plotpy.coords import axes_to_canvas
1718
from plotpy.interfaces import (
1819
IBaseImageItem,
@@ -538,7 +539,7 @@ def get_plot_qrect(plot: qwt.plot.QwtPlot, p0: QPointF, p1: QPointF) -> QRectF:
538539
Returns:
539540
Plot rectangle
540541
"""
541-
ax, ay = plot.X_BOTTOM, plot.Y_LEFT
542+
ax, ay = X_BOTTOM, Y_LEFT
542543
p0x, p0y = plot.invTransform(ax, p0.x()), plot.invTransform(ay, p0.y())
543544
p1x, p1y = plot.invTransform(ax, p1.x() + 1), plot.invTransform(ay, p1.y() + 1)
544545
return QC.QRectF(p0x, p0y, p1x - p0x, p1y - p0y)

plotpy/panels/contrastadjustment.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from qtpy import QtWidgets as QW
2929

3030
from plotpy.config import CONF, IS_DARK, _
31-
from plotpy.constants import ID_CONTRAST, PlotType
31+
from plotpy.constants import ID_CONTRAST, Y_LEFT, Y_RIGHT, PlotType
3232
from plotpy.interfaces import IPanel, IVoiImageItemType
3333
from plotpy.items import HistogramItem, XRangeSelection
3434
from plotpy.lutrange import lut_range_threshold
@@ -61,7 +61,7 @@ class LevelsHistogram(BasePlot):
6161
#: the base plot class (see :py:attr:`.BasePlot.SIG_LUT_CHANGED`).
6262
SIG_VOI_CHANGED = QC.Signal()
6363

64-
def __init__(self, parent: QWidget = None) -> None:
64+
def __init__(self, parent: QWidget | None = None) -> None:
6565
super().__init__(
6666
parent=parent,
6767
options=BasePlotOptions(title="", section="histogram", type="curve"),
@@ -82,8 +82,8 @@ def __init__(self, parent: QWidget = None) -> None:
8282
self.set_active_item(self.range)
8383

8484
self.setMinimumHeight(80)
85-
self.setAxisMaxMajor(self.Y_LEFT, 5)
86-
self.setAxisMaxMinor(self.Y_LEFT, 0)
85+
self.setAxisMaxMajor(Y_LEFT, 5)
86+
self.setAxisMaxMinor(Y_LEFT, 0)
8787

8888
if parent is None:
8989
self.set_axis_title("bottom", "Levels")
@@ -255,7 +255,7 @@ def axis_parameters_changed(self, plot: BasePlot, axis_id: int) -> None:
255255
Args:
256256
axis_id: axis ID
257257
"""
258-
if axis_id == BasePlot.Y_RIGHT:
258+
if axis_id == Y_RIGHT:
259259
# Colormap bounds changed, we need to update the range accordingly:
260260
self.active_item_changed(plot)
261261

plotpy/panels/csection/csitem.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from qtpy import QtCore as QC
1111

1212
from plotpy.config import _
13+
from plotpy.constants import X_BOTTOM, Y_LEFT
1314
from plotpy.coords import axes_to_canvas, canvas_to_axes
1415
from plotpy.interfaces import IBasePlotItem
1516
from plotpy.items.curve.errorbar import ErrorBarCurveItem
@@ -96,7 +97,7 @@ def get_plot_y_section(obj, apply_lut=False):
9697
"""
9798
x0, _y0 = get_object_coordinates(obj)
9899
plot = obj.plot()
99-
ymap = plot.canvasMap(plot.Y_LEFT)
100+
ymap = plot.canvasMap(Y_LEFT)
100101
yc0, yc1 = ymap.p1(), ymap.p2()
101102
if plot.get_axis_direction("left"):
102103
yc1, yc0 = yc0, yc1
@@ -361,9 +362,9 @@ def update_scale(self):
361362
""" """
362363
plot = self.plot()
363364
if self.orientation() == QC.Qt.Orientation.Vertical:
364-
axis_id = plot.Y_LEFT
365+
axis_id = Y_LEFT
365366
else:
366-
axis_id = plot.X_BOTTOM
367+
axis_id = X_BOTTOM
367368
source = self.get_source_image()
368369
sdiv = source.plot().axisScaleDiv(axis_id)
369370
plot.setAxisScale(axis_id, sdiv.lowerBound(), sdiv.upperBound())

plotpy/panels/csection/csplot.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@
99
from qtpy import QtWidgets as QW
1010

1111
from plotpy.config import CONF, _
12-
from plotpy.constants import LUT_MAX, PlotType
12+
from plotpy.constants import AXIS_IDS, LUT_MAX, X_BOTTOM, Y_LEFT, PlotType
1313
from plotpy.interfaces import ICSImageItemType
1414
from plotpy.panels.csection.csitem import (
1515
LineCrossSectionItem,
1616
ObliqueCrossSectionItem,
1717
XCrossSectionItem,
1818
YCrossSectionItem,
1919
)
20-
from plotpy.plot.base import BasePlot, BasePlotOptions
2120
from plotpy.styles.curve import CurveParam
2221

2322
LUT_AXIS_TITLE = _("LUT scale") + (" (0-%d)" % LUT_MAX)
@@ -28,6 +27,7 @@
2827

2928
from plotpy.items import BaseImageItem
3029
from plotpy.panels.csection.csitem import CrossSectionItem
30+
from plotpy.plot.base import BasePlot
3131

3232

3333
class BaseCrossSectionPlot(BasePlot):
@@ -49,7 +49,7 @@ class BaseCrossSectionPlot(BasePlot):
4949
def __init__(self, parent: QWidget | None = None) -> None:
5050
super().__init__(
5151
parent=parent,
52-
options=BasePlotOptions(title="", section="cross_section", type="curve"),
52+
options=dict(title="", section="cross_section", type="curve"),
5353
)
5454
self.perimage_mode = True
5555
self.autoscale_mode = True
@@ -110,7 +110,7 @@ def connect_plot(self, plot: BasePlot) -> None:
110110
plot.SIG_AXIS_DIRECTION_CHANGED.connect(self.axis_dir_changed)
111111
plot.SIG_PLOT_AXIS_CHANGED.connect(self.plot_axis_changed)
112112
self.plot_labels_changed(plot)
113-
for axis_id in plot.AXIS_IDS:
113+
for axis_id in AXIS_IDS:
114114
self.axis_dir_changed(plot, axis_id)
115115
self.items_changed(plot)
116116

@@ -364,8 +364,8 @@ def lut_changed(self, plot: BasePlot) -> None:
364364

365365

366366
class HorizontalCrossSectionPlot(BaseCrossSectionPlot):
367-
CS_AXIS = BasePlot.X_BOTTOM
368-
Z_AXIS = BasePlot.Y_LEFT
367+
CS_AXIS = X_BOTTOM
368+
Z_AXIS = Y_LEFT
369369

370370
def plot_labels_changed(self, plot: BasePlot) -> None:
371371
"""Plot labels have changed
@@ -391,8 +391,8 @@ def axis_dir_changed(self, plot: BasePlot, axis_id: str) -> None:
391391

392392

393393
class VerticalCrossSectionPlot(BaseCrossSectionPlot):
394-
CS_AXIS = BasePlot.Y_LEFT
395-
Z_AXIS = BasePlot.X_BOTTOM
394+
CS_AXIS = Y_LEFT
395+
Z_AXIS = X_BOTTOM
396396
Z_MAX_MAJOR = 3
397397

398398
def plot_labels_changed(self, plot: BasePlot) -> None:
@@ -419,7 +419,6 @@ def axis_dir_changed(self, plot: BasePlot, axis_id: str) -> None:
419419

420420

421421
class XYCrossSectionMixin:
422-
423422
LABEL_TEXT = _("Enable a marker")
424423

425424
def connect_plot(self, plot: BasePlot) -> None:

plotpy/plot/base.py

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from qtpy import QtWidgets as QW
3232
from qtpy.QtPrintSupport import QPrinter
3333

34+
from plotpy import constants as cst
3435
from plotpy import io
3536
from plotpy.config import CONF, _
3637
from plotpy.constants import PARAMETERS_TITLE_ICON, PlotType
@@ -149,14 +150,7 @@ class BasePlot(qwt.QwtPlot):
149150
options: plot options
150151
"""
151152

152-
Y_LEFT, Y_RIGHT, X_BOTTOM, X_TOP = (
153-
qwt.QwtPlot.yLeft,
154-
qwt.QwtPlot.yRight,
155-
qwt.QwtPlot.xBottom,
156-
qwt.QwtPlot.xTop,
157-
)
158-
# # To be replaced by (in the near future):
159-
# Y_LEFT, Y_RIGHT, X_BOTTOM, X_TOP = range(4)
153+
Y_LEFT, Y_RIGHT, X_BOTTOM, X_TOP = cst.Y_LEFT, cst.Y_RIGHT, cst.X_BOTTOM, cst.X_TOP
160154
AXIS_IDS = (Y_LEFT, Y_RIGHT, X_BOTTOM, X_TOP)
161155
AXIS_NAMES = {"left": Y_LEFT, "right": Y_RIGHT, "bottom": X_BOTTOM, "top": X_TOP}
162156
AXIS_TYPES = {"lin": qwt.QwtLinearScaleEngine, "log": qwt.QwtLogScaleEngine}
@@ -331,7 +325,7 @@ def __init__(
331325
options.yreverse = False
332326
self.__autoYReverse = True
333327

334-
self.colormap_axis = self.Y_RIGHT
328+
self.colormap_axis = cst.Y_RIGHT
335329

336330
self.__autoColorBarEnabled = False
337331
if options.force_colorbar_enabled or self.options.type == PlotType.IMAGE:
@@ -1912,7 +1906,7 @@ def edit_axis_parameters(self, axis_id: int) -> None:
19121906
axis_id (int): the axis ID
19131907
"""
19141908
if axis_id != self.colormap_axis:
1915-
if axis_id in (self.Y_LEFT, self.Y_RIGHT):
1909+
if axis_id in (cst.Y_LEFT, cst.Y_RIGHT):
19161910
title = _("Y Axis")
19171911
else:
19181912
title = _("X Axis")
@@ -2044,11 +2038,11 @@ def get_axis_direction(self, axis_id: int | str) -> bool:
20442038
Return axis direction of increasing values
20452039
20462040
Args:
2047-
axis_id (int | str): axis id (BasePlot.Y_LEFT, BasePlot.X_BOTTOM, ...)
2041+
axis_id: axis id (constants.Y_LEFT, constants.X_BOTTOM, ...)
20482042
or string: 'bottom', 'left', 'top' or 'right'
20492043
20502044
Returns:
2051-
bool: False (default)
2045+
False (default)
20522046
"""
20532047
axis_id = self.get_axis_id(axis_id)
20542048
return self.axes_reverse[axis_id]
@@ -2058,8 +2052,8 @@ def set_axis_direction(self, axis_id: int | str, reverse: bool = False) -> None:
20582052
Set axis direction of increasing values
20592053
20602054
Args:
2061-
axis_id (int | str): axis id (BasePlot.Y_LEFT, BasePlot.X_BOTTOM, ...)
2062-
or string: 'bottom', 'left', 'top' or 'right'
2055+
axis_id: axis id (constants.Y_LEFT, constants.X_BOTTOM, ...)
2056+
or string: 'bottom', 'left', 'top' or 'right'
20632057
reverse (bool): False (default)
20642058
20652059
If reverse is False:
@@ -2211,10 +2205,10 @@ def get_current_aspect_ratio(self) -> float | None:
22112205
(this happens when the plot has been shrunk to a size so that the
22122206
width is zero)
22132207
"""
2214-
dx = self.axisScaleDiv(self.X_BOTTOM).range()
2215-
dy = self.axisScaleDiv(self.Y_LEFT).range()
2216-
h = self.canvasMap(self.Y_LEFT).pDist()
2217-
w = self.canvasMap(self.X_BOTTOM).pDist()
2208+
dx = self.axisScaleDiv(cst.X_BOTTOM).range()
2209+
dy = self.axisScaleDiv(cst.Y_LEFT).range()
2210+
h = self.canvasMap(cst.Y_LEFT).pDist()
2211+
w = self.canvasMap(cst.X_BOTTOM).pDist()
22182212
try:
22192213
return fabs((h * dx) / (w * dy))
22202214
except ZeroDivisionError:
@@ -2260,8 +2254,8 @@ def apply_aspect_ratio(self, full_scale: bool = False) -> None:
22602254
abs(current_aspect - self.__aspect_ratio) < self.EPSILON_ASPECT_RATIO
22612255
):
22622256
return
2263-
ymap = self.canvasMap(self.Y_LEFT)
2264-
xmap = self.canvasMap(self.X_BOTTOM)
2257+
ymap = self.canvasMap(cst.Y_LEFT)
2258+
xmap = self.canvasMap(cst.X_BOTTOM)
22652259
h = ymap.pDist()
22662260
w = xmap.pDist()
22672261
dx1, dy1 = xmap.sDist(), fabs(ymap.sDist())

plotpy/plot/plotwidget.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from qtpy.QtWidgets import QWidget # only to help intersphinx find QWidget
1616

1717
from plotpy.config import _
18-
from plotpy.constants import PlotType
18+
from plotpy.constants import X_BOTTOM, Y_LEFT, PlotType
1919
from plotpy.plot.base import BasePlot, BasePlotOptions
2020
from plotpy.plot.manager import PlotManager
2121

@@ -989,8 +989,8 @@ def add_plot(
989989
if sync and len(self.subplotwidget.plots) > 1:
990990
syncaxis = self.manager.synchronize_axis
991991
for i_plot in range(len(self.subplotwidget.plots) - 1):
992-
syncaxis(BasePlot.X_BOTTOM, [plot_id, f"{i_plot + 1}"])
993-
syncaxis(BasePlot.Y_LEFT, [plot_id, f"{i_plot + 1}"])
992+
syncaxis(X_BOTTOM, [plot_id, f"{i_plot + 1}"])
993+
syncaxis(Y_LEFT, [plot_id, f"{i_plot + 1}"])
994994

995995
def get_plots(self) -> list[BasePlot]:
996996
"""Return the plots

plotpy/styles/axes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from qwt import QwtPlot
2121

2222
from plotpy.config import _
23+
from plotpy.constants import X_BOTTOM, Y_LEFT, Y_RIGHT
2324
from plotpy.styles.base import FontItem
2425

2526
if TYPE_CHECKING:
@@ -197,7 +198,7 @@ def update_item(self, item: BaseImageItem) -> None:
197198
plot.set_plot_limits(self.xmin, self.xmax, self.ymin, self.ymax)
198199
item.set_lut_range([self.zmin, self.zmax])
199200
plot.update_colormap_axis(item)
200-
for axis_id in (plot.X_BOTTOM, plot.Y_LEFT, plot.Y_RIGHT):
201+
for axis_id in (X_BOTTOM, Y_LEFT, Y_RIGHT):
201202
plot.SIG_AXIS_PARAMETERS_CHANGED.emit(axis_id)
202203

203204
# TODO: remove this method in a future release
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Licensed under the terms of the BSD 3-Clause
4+
# (see plotpy/LICENSE for details)
5+
6+
"""Test cyclic import issue"""
7+
8+
# pylint: disable=import-outside-toplevel
9+
# pylint: disable=unused-import
10+
11+
12+
def test_tools_cyclic_import():
13+
"""Test cyclic import issue"""
14+
# Importing one tool from each module to check if there is a cyclic import issue
15+
from plotpy.tools import (
16+
AnnotatedPointTool, # noqa: F401
17+
AverageCrossSectionTool, # noqa: F401
18+
CurveStatsTool, # noqa: F401
19+
DoAutoscaleTool, # noqa: F401
20+
ItemCenterTool, # noqa: F401
21+
OpenImageTool, # noqa: F401
22+
PointTool, # noqa: F401
23+
PrintTool, # noqa: F401
24+
RectangularActionTool, # noqa: F401
25+
SelectTool, # noqa: F401
26+
)
27+
28+
29+
if __name__ == "__main__":
30+
test_tools_cyclic_import()

0 commit comments

Comments
 (0)