Skip to content

Commit 3c286f2

Browse files
committed
Black formatting
1 parent 0b74ae8 commit 3c286f2

2 files changed

Lines changed: 57 additions & 4 deletions

File tree

ultraplot/axes/geo.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,8 +1539,12 @@ def _sync_edge_lat_labels(self) -> None:
15391539
self._clear_edge_lat_labels()
15401540
return
15411541

1542-
left_labels = adapter.labels_for_sides(left=True).get("left", []) if left_on else []
1543-
right_labels = adapter.labels_for_sides(right=True).get("right", []) if right_on else []
1542+
left_labels = (
1543+
adapter.labels_for_sides(left=True).get("left", []) if left_on else []
1544+
)
1545+
right_labels = (
1546+
adapter.labels_for_sides(right=True).get("right", []) if right_on else []
1547+
)
15441548
if not left_labels and not right_labels:
15451549
self._clear_edge_lat_labels()
15461550
return
@@ -2813,7 +2817,9 @@ def _update_gridlines(
28132817
lonlines_mod = (lonlines + 180) % 360 - 180 # only for cartopy
28142818
# Preserve distinct -180/180 ticks so both map edges can be labeled.
28152819
eps = 1e-10
2816-
lonlines_mod = np.where(np.isclose(lonlines, -180), -180 + eps, lonlines_mod)
2820+
lonlines_mod = np.where(
2821+
np.isclose(lonlines, -180), -180 + eps, lonlines_mod
2822+
)
28172823
lonlines_mod = np.where(np.isclose(lonlines, 180), 180 - eps, lonlines_mod)
28182824
lonlines = lonlines_mod
28192825
gl.xlocator = mticker.FixedLocator(lonlines)

ultraplot/tests/test_figure.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import pytest, ultraplot as uplt, numpy as np
1+
import multiprocessing as mp
2+
import os
3+
4+
import numpy as np
5+
import pytest
6+
import ultraplot as uplt
27

38

49
def test_unsharing_after_creation(rng):
@@ -146,6 +151,48 @@ def test_toggle_input_axis_sharing():
146151
fig._toggle_axis_sharing(which="does not exist")
147152

148153

154+
def _layout_signature() -> tuple:
155+
fig, ax = uplt.subplots(ncols=2, nrows=2)
156+
for axi in ax:
157+
axi.plot([0, 1], [0, 1], label="line")
158+
axi.set_xlabel("X label")
159+
axi.set_ylabel("Y label")
160+
fig.suptitle("Title")
161+
fig.legend()
162+
fig.canvas.draw()
163+
signature = tuple(
164+
tuple(np.round(axi.get_position().bounds, 6))
165+
for axi in fig.axes
166+
if axi.get_visible()
167+
)
168+
uplt.close(fig)
169+
return signature
170+
171+
172+
def _layout_worker(queue):
173+
queue.put(_layout_signature())
174+
175+
176+
def test_layout_deterministic_across_runs():
177+
"""
178+
Layout should be deterministic for identical inputs.
179+
"""
180+
positions = [_layout_signature() for _ in range(3)]
181+
assert all(p == positions[0] for p in positions)
182+
183+
# Probe mode: exercise multiple processes to catch nondeterminism.
184+
if os.environ.get("ULTRAPLOT_LAYOUT_PROBE") == "1":
185+
ctx = mp.get_context("spawn")
186+
queue = ctx.Queue()
187+
workers = [ctx.Process(target=_layout_worker, args=(queue,)) for _ in range(4)]
188+
for proc in workers:
189+
proc.start()
190+
proc_positions = [queue.get() for _ in workers]
191+
for proc in workers:
192+
proc.join()
193+
assert all(p == proc_positions[0] for p in proc_positions)
194+
195+
149196
def test_suptitle_alignment():
150197
"""
151198
Test that suptitle uses the original centering behavior with includepanels parameter.

0 commit comments

Comments
 (0)