1
1
from copy import copy
2
- from typing import Any , Dict , Optional , TYPE_CHECKING , Union , cast
2
+ from typing import Any , Dict , Optional , TYPE_CHECKING , Union
3
3
4
4
import pystac
5
5
from pystac .utils import make_absolute_href , make_relative_href , is_absolute_href
@@ -52,11 +52,6 @@ class Link:
52
52
"""The relation of the link (e.g. 'child', 'item'). Registered rel Types are
53
53
preferred. See :class:`~pystac.RelType` for common media types."""
54
54
55
- target : Union [str , "STACObject_Type" ]
56
- """The target of the link. If the link is unresolved, or the link is to something
57
- that is not a STACObject, the target is an HREF. If resolved, the target is a
58
- STACObject."""
59
-
60
55
media_type : Optional [str ]
61
56
"""Optional description of the media type. Registered Media Types are preferred.
62
57
See :class:`~pystac.MediaType` for common media types."""
@@ -82,7 +77,12 @@ def __init__(
82
77
extra_fields : Optional [Dict [str , Any ]] = None ,
83
78
) -> None :
84
79
self .rel = rel
85
- self .target = target
80
+ if isinstance (target , str ):
81
+ self ._target_href : Optional [str ] = target
82
+ self ._target_object = None
83
+ else :
84
+ self ._target_href = None
85
+ self ._target_object = target
86
86
self .media_type = media_type
87
87
self .title = title
88
88
self .extra_fields = extra_fields or {}
@@ -119,10 +119,10 @@ def get_href(self) -> Optional[str]:
119
119
In all other cases, this method will return an absolute HREF.
120
120
"""
121
121
# get the self href
122
- if self .is_resolved () :
123
- href = cast ( pystac . STACObject , self .target ) .get_self_href ()
122
+ if self ._target_object :
123
+ href = self ._target_object .get_self_href ()
124
124
else :
125
- href = cast ( Optional [ str ], self .target )
125
+ href = self ._target_href
126
126
127
127
if href and is_absolute_href (href ) and self .owner and self .owner .get_root ():
128
128
root = self .owner .get_root ()
@@ -158,16 +158,55 @@ def get_absolute_href(self) -> Optional[str]:
158
158
from this link; however, if the link is relative, has no owner,
159
159
and has an unresolved target, this will return a relative HREF.
160
160
"""
161
- if self .is_resolved () :
162
- href = cast ( pystac . STACObject , self .target ) .get_self_href ()
161
+ if self ._target_object :
162
+ href = self ._target_object .get_self_href ()
163
163
else :
164
- href = cast ( Optional [ str ], self .target )
164
+ href = self ._target_href
165
165
166
166
if href is not None and self .owner is not None :
167
167
href = make_absolute_href (href , self .owner .get_self_href ())
168
168
169
169
return href
170
170
171
+ @property
172
+ def target (self ) -> Union [str , "STACObject_Type" ]:
173
+ """The target of the link. If the link is unresolved, or the link is to something
174
+ that is not a STACObject, the target is an HREF. If resolved, the target is a
175
+ STACObject."""
176
+ if self ._target_object :
177
+ return self ._target_object
178
+ elif self ._target_href :
179
+ return self ._target_href
180
+ else :
181
+ raise ValueError ("No target defined for link." )
182
+
183
+ @target .setter
184
+ def target (self , target : Union [str , "STACObject_Type" ]) -> None :
185
+ """Sets this link's target to a string or a STAC object."""
186
+ if isinstance (target , str ):
187
+ self ._target_href = target
188
+ self ._target_object = None
189
+ else :
190
+ self ._target_href = None
191
+ self ._target_object = target
192
+
193
+ def get_target_str (self ) -> Optional [str ]:
194
+ """Returns this link's target as a string.
195
+
196
+ If a string href was provided, returns that. If not, tries to resolve
197
+ the self link of the target object.
198
+ """
199
+ if self ._target_href :
200
+ return self ._target_href
201
+ elif self ._target_object :
202
+ return self ._target_object .get_self_href ()
203
+ else :
204
+ return None
205
+
206
+ def has_target_href (self ) -> bool :
207
+ """Returns true if this link has a string href in its target information."""
208
+ return self ._target_href is not None
209
+
171
210
def __repr__ (self ) -> str :
172
211
return "<Link rel={} target={}>" .format (self .rel , self .target )
173
212
@@ -180,8 +219,10 @@ def resolve_stac_object(self, root: Optional["Catalog_Type"] = None) -> "Link":
180
219
If provided, the root's resolved object cache is used to search for
181
220
previously resolved instances of the STAC object.
182
221
"""
183
- if isinstance (self .target , str ):
184
- target_href = self .target
222
+ if self ._target_object :
223
+ pass
224
+ elif self ._target_href :
225
+ target_href = self ._target_href
185
226
186
227
# If it's a relative link, base it off the parent.
187
228
if not is_absolute_href (target_href ):
@@ -221,17 +262,17 @@ def resolve_stac_object(self, root: Optional["Catalog_Type"] = None) -> "Link":
221
262
if root is not None :
222
263
obj = root ._resolved_objects .get_or_cache (obj )
223
264
obj .set_root (root )
265
+ self ._target_object = obj
224
266
else :
225
- obj = self .target
226
-
227
- self .target = obj
267
+ raise ValueError ("Cannot resolve STAC object without a target" )
228
268
229
269
if (
230
270
self .owner
231
271
and self .rel in [pystac .RelType .CHILD , pystac .RelType .ITEM ]
232
272
and isinstance (self .owner , pystac .Catalog )
233
273
):
234
- self .target .set_parent (self .owner )
274
+ assert self ._target_object
275
+ self ._target_object .set_parent (self .owner )
235
276
236
277
return self
237
278
@@ -241,7 +282,7 @@ def is_resolved(self) -> bool:
241
282
Returns:
242
283
bool: True if this link is resolved.
243
284
"""
244
- return not isinstance ( self .target , str )
285
+ return self ._target_object is not None
245
286
246
287
def to_dict (self ) -> Dict [str , Any ]:
247
288
"""Generate a dictionary representing the JSON of this serialized Link.
0 commit comments