Skip to content

Commit 5d6eb9a

Browse files
astrofrogeteq
authored andcommitted
Merge pull request #5021 from eteq/fix-frame-attr-set-delayed
includes manual merge for 1.0.x Fix SkyCoord AttributeError when a new frame is created after a SkyCoord has been inited
1 parent 64ee110 commit 5d6eb9a

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,10 @@ Bug Fixes
15241524

15251525
- ``astropy.coordinates``
15261526

1527+
- ``SkyCoord`` objects created before a new frame which has frame attributes
1528+
is created no longer raise ``AttributeError`` when the new attributes are
1529+
accessed [#5021]
1530+
15271531
- Fix some errors in the implementation of aberration for ``get_sun``. [#4979]
15281532

15291533
- ``astropy.cosmology``

astropy/coordinates/sky_coordinate.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,17 @@ def __getattr__(self, attr):
369369
if attr in self.frame.get_frame_attr_names():
370370
return getattr(self.frame, attr)
371371
else:
372-
return getattr(self, '_' + attr)
372+
try:
373+
return getattr(self, '_' + attr)
374+
except AttributeError:
375+
# this can happen because FRAME_ATTR_NAMES_SET is
376+
# dynamic. So if a frame is added to the transform
377+
# graph after this SkyCoord was created, the "real"
378+
# underlying attribute - e.g. `_equinox` does not exist
379+
# on the SkyCoord. So we add this case to just use
380+
# None, as it wouldn't have been possible for the user
381+
# to have set the value until the frame existed anyway
382+
return None
373383

374384
# Some attributes might not fall in the above category but still
375385
# are available through self._sky_coord_frame.

astropy/coordinates/tests/test_sky_coord.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
from ..representation import REPRESENTATION_CLASSES
2121
from ...coordinates import (ICRS, FK4, FK5, Galactic, SkyCoord, Angle,
2222
SphericalRepresentation, CartesianRepresentation,
23-
UnitSphericalRepresentation, AltAz)
23+
UnitSphericalRepresentation, AltAz,
24+
BaseCoordinateFrame, FrameAttribute,
25+
frame_transform_graph)
2426
from ...coordinates import Latitude, Longitude, EarthLocation
2527
from ...time import Time
2628
from ...utils import minversion
@@ -1135,3 +1137,40 @@ def test_getitem_representation():
11351137
sc = SkyCoord([1, 1] * u.deg, [2, 2] * u.deg)
11361138
sc.representation = 'cartesian'
11371139
assert sc[0].representation is CartesianRepresentation
1140+
1141+
1142+
def test_frame_attr_changes():
1143+
"""
1144+
This tests the case where a frame is added with a new frame attribute after
1145+
a SkyCoord has been created. This is necessary because SkyCoords get the
1146+
attributes set at creation time, but the set of attributes can change as
1147+
frames are added or removed from the transform graph. This makes sure that
1148+
everything continues to work consistently.
1149+
"""
1150+
sc_before = SkyCoord(1*u.deg, 2*u.deg, frame='icrs')
1151+
1152+
assert 'fakeattr' not in dir(sc_before)
1153+
1154+
class FakeFrame(BaseCoordinateFrame):
1155+
fakeattr = FrameAttribute()
1156+
1157+
# doesn't matter what this does as long as it just puts the frame in the
1158+
# transform graph
1159+
transset = (ICRS, FakeFrame, lambda c,f:c)
1160+
frame_transform_graph.add_transform(*transset)
1161+
try:
1162+
assert 'fakeattr' in dir(sc_before)
1163+
assert sc_before.fakeattr is None
1164+
1165+
sc_after1 = SkyCoord(1*u.deg, 2*u.deg, frame='icrs')
1166+
assert 'fakeattr' in dir(sc_after1)
1167+
assert sc_after1.fakeattr is None
1168+
1169+
sc_after2 = SkyCoord(1*u.deg, 2*u.deg, frame='icrs', fakeattr=1)
1170+
assert sc_after2.fakeattr == 1
1171+
finally:
1172+
frame_transform_graph.remove_transform(*transset)
1173+
1174+
assert 'fakeattr' not in dir(sc_before)
1175+
assert 'fakeattr' not in dir(sc_after1)
1176+
assert 'fakeattr' not in dir(sc_after2)

0 commit comments

Comments
 (0)