Skip to content

Commit 9e0e3b5

Browse files
authored
Delegate external axes methods with guardrails (#514)
* Delegate external axes methods with guardrails Route attribute access to external axes by default while keeping UltraPlot-specific formatting and container overrides on the parent. * Simplify external axes delegation Delegate missing methods to the external axes via __getattr__ and keep a small blocklist for UltraPlot formatting/guide APIs.
1 parent f97c605 commit 9e0e3b5

1 file changed

Lines changed: 12 additions & 18 deletions

File tree

ultraplot/axes/container.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ class ExternalAxesContainer(CartesianAxes):
6161
``external_padding=2`` or ``external_padding=0`` to disable padding entirely.
6262
"""
6363

64+
_EXTERNAL_DELEGATE_BLOCKLIST = {
65+
# Keep UltraPlot formatting/guide behaviors on the container.
66+
"format",
67+
"colorbar",
68+
"legend",
69+
"set_title",
70+
}
71+
6472
def __init__(
6573
self, *args, external_axes_class=None, external_axes_kwargs=None, **kwargs
6674
):
@@ -799,28 +807,14 @@ def get_tightbbox(self, renderer, *args, **kwargs):
799807

800808
def __getattr__(self, name):
801809
"""
802-
Delegate attribute access to the external axes when not found on container.
803-
804-
This allows the container to act as a transparent wrapper, forwarding
805-
plotting methods and other attributes to the external axes.
810+
Delegate missing attributes to the external axes unless blocked.
806811
"""
807-
# Avoid infinite recursion for private attributes
808-
# But allow parent class lookups during initialization
809-
if name.startswith("_"):
810-
# During initialization, let parent class handle private attributes
811-
# This prevents interfering with parent class setup
812+
if name in self._EXTERNAL_DELEGATE_BLOCKLIST:
812813
raise AttributeError(
813814
f"'{type(self).__name__}' object has no attribute '{name}'"
814815
)
815-
816-
# Try to get from external axes if it exists
817-
if hasattr(self, "_external_axes") and self._external_axes is not None:
818-
try:
819-
return getattr(self._external_axes, name)
820-
except AttributeError:
821-
pass
822-
823-
# Not found anywhere
816+
if self._external_axes is not None:
817+
return getattr(self._external_axes, name)
824818
raise AttributeError(
825819
f"'{type(self).__name__}' object has no attribute '{name}'"
826820
)

0 commit comments

Comments
 (0)