Skip to content

Commit f10a7de

Browse files
m-mohrgadomski
authored andcommitted
Add keep_parent parameter to add_child and add_item #1116
1 parent 2175c14 commit f10a7de

File tree

4 files changed

+74
-6
lines changed

4 files changed

+74
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- `recursive` to Catalog and Collection `get_items()` to walk the sub-catalogs and sub-collections ([#1075](https://github.com/stac-utils/pystac/pull/1075))
1010
- MGRS Extension ([#1088](https://github.com/stac-utils/pystac/pull/1088))
1111
- All HTTP requests are logged when level is set to `logging.DEBUG` ([#1096](https://github.com/stac-utils/pystac/pull/1096))
12+
- `keep_parent` to Catalog `add_item` and `add_child` to avoid overriding existing parents ([#1117](https://github.com/stac-utils/pystac/pull/1117))
1213

1314
### Changed
1415

pystac/catalog.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,12 @@ def add_child(
240240
child: Union["Catalog", Collection],
241241
title: Optional[str] = None,
242242
strategy: Optional[HrefLayoutStrategy] = None,
243+
keep_parent: bool = False,
243244
) -> None:
244245
"""Adds a link to a child :class:`~pystac.Catalog` or
245246
:class:`~pystac.Collection`. This method will set the child's parent to this
246-
object, and its root to this Catalog's root.
247+
object (except if a parent is set and keep_parent is true).
248+
It will always set its root to this Catalog's root.
247249
248250
Args:
249251
child : The child to add.
@@ -261,7 +263,8 @@ def add_child(
261263
strategy = BestPracticesLayoutStrategy()
262264

263265
child.set_root(self.get_root())
264-
child.set_parent(self)
266+
if child.get_parent() is None or not keep_parent:
267+
child.set_parent(self)
265268

266269
# set self link
267270
self_href = self.get_self_href()
@@ -287,10 +290,12 @@ def add_item(
287290
item: Item,
288291
title: Optional[str] = None,
289292
strategy: Optional[HrefLayoutStrategy] = None,
293+
keep_parent: bool = False,
290294
) -> None:
291295
"""Adds a link to an :class:`~pystac.Item`.
292-
This method will set the item's parent to this object, and its root to
293-
this Catalog's root.
296+
This method will set the item's parent to this object (except if a parent
297+
is set and keep_parent is true).
298+
It will always set its root to this Catalog's root.
294299
295300
Args:
296301
item : The item to add.
@@ -308,7 +313,8 @@ def add_item(
308313
strategy = BestPracticesLayoutStrategy()
309314

310315
item.set_root(self.get_root())
311-
item.set_parent(self)
316+
if item.get_parent() is None or not keep_parent:
317+
item.set_parent(self)
312318

313319
# set self link
314320
self_href = self.get_self_href()

pystac/collection.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,9 @@ def add_item(
553553
item: Item,
554554
title: Optional[str] = None,
555555
strategy: Optional[HrefLayoutStrategy] = None,
556+
keep_parent: bool = False,
556557
) -> None:
557-
super().add_item(item, title, strategy)
558+
super().add_item(item, title, strategy, keep_parent)
558559
item.set_collection(self)
559560

560561
def to_dict(

tests/test_catalog.py

+60
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,66 @@ def test_add_child_throws_if_item(self) -> None:
222222
with pytest.raises(pystac.STACError):
223223
cat.add_child(item) # type:ignore
224224

225+
def test_add_child_override_parent(self) -> None:
226+
parent1 = Catalog(id="parent1", description="test1")
227+
parent2 = Catalog(id="parent2", description="test2")
228+
child = Catalog(id="child", description="test3")
229+
assert child.get_parent() is None
230+
231+
parent1.add_child(child)
232+
assert child.get_parent() is parent1
233+
234+
parent2.add_child(child)
235+
assert child.get_parent() is parent2
236+
237+
def test_add_child_keep_parent(self) -> None:
238+
parent1 = Catalog(id="parent1", description="test1")
239+
parent2 = Catalog(id="parent2", description="test2")
240+
child = Catalog(id="child", description="test3")
241+
assert child.get_parent() is None
242+
243+
parent1.add_child(child, keep_parent=True)
244+
assert child.get_parent() is parent1
245+
246+
parent2.add_child(child, keep_parent=True)
247+
assert child.get_parent() is parent1
248+
249+
def test_add_item_override_parent(self) -> None:
250+
parent1 = Catalog(id="parent1", description="test1")
251+
parent2 = Catalog(id="parent2", description="test2")
252+
child = Item(
253+
id="child",
254+
geometry=None,
255+
bbox=None,
256+
datetime=datetime.now(),
257+
properties={},
258+
)
259+
assert child.get_parent() is None
260+
261+
parent1.add_item(child)
262+
assert child.get_parent() is parent1
263+
264+
parent2.add_item(child)
265+
assert child.get_parent() is parent2
266+
267+
def test_add_item_keep_parent(self) -> None:
268+
parent1 = Catalog(id="parent1", description="test1")
269+
parent2 = Catalog(id="parent2", description="test2")
270+
child = Item(
271+
id="child",
272+
geometry=None,
273+
bbox=None,
274+
datetime=datetime.now(),
275+
properties={},
276+
)
277+
assert child.get_parent() is None
278+
279+
parent1.add_item(child, keep_parent=True)
280+
assert child.get_parent() is parent1
281+
282+
parent2.add_item(child, keep_parent=True)
283+
assert child.get_parent() is parent1
284+
225285
def test_add_item_throws_if_child(self) -> None:
226286
cat = TestCases.case_1()
227287
child = next(iter(cat.get_children()))

0 commit comments

Comments
 (0)