Skip to content

Commit 1ead0d5

Browse files
committed
Ability to add ItemCollections
1 parent 702a26f commit 1ead0d5

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

pystac/item_collection.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class ItemCollection(Collection[pystac.Item]):
1616
1717
All :class:`~pystac.Item` instances passed to the :class:`~ItemCollection` instance
1818
during instantiation are cloned and have their ``"root"`` URL cleared. Instances of
19-
this class implement the abstract methods of :class:`typing.Collection` (see
20-
below for examples using these methods).
19+
this class implement the abstract methods of :class:`typing.Collection` and can also
20+
be added together (see below for examples using these methods).
2121
2222
Any additional top-level fields in the FeatureCollection are retained in
2323
:attr:`~ItemCollection.extra_fields` by the :meth:`~ItemCollection.from_dict` and
@@ -58,6 +58,22 @@ class ItemCollection(Collection[pystac.Item]):
5858
>>> item_collection = ItemCollection(items=[item], clone_items=False)
5959
>>> assert item in item_collection
6060
61+
Combine :class:`~ItemCollection` instances
62+
63+
>>> item_1: Item = ...
64+
>>> item_2: Item = ...
65+
>>> item_3: Item = ...
66+
>>> item_collection_1 = ItemCollection(
67+
... items=[item_1, item_2],
68+
... clone_items=False
69+
... )
70+
>>> item_collection_2 = ItemCollection(
71+
... items=[item_2, item_3],
72+
... clone_items=False
73+
... )
74+
>>> combined = item_collection_1 + item_collection_2
75+
>>> assert len(combined) == 3
76+
# If an item is present in both ItemCollections it will only be added once
6177
"""
6278

6379
items: List[pystac.Item]
@@ -95,6 +111,17 @@ def __len__(self) -> int:
95111
def __contains__(self, __x: object) -> bool:
96112
return __x in self.items
97113

114+
def __add__(self, other: object) -> "ItemCollection":
115+
if not isinstance(other, ItemCollection):
116+
return NotImplemented
117+
118+
combined = []
119+
for item in self.items + other.items:
120+
if item not in combined:
121+
combined.append(item)
122+
123+
return ItemCollection(items=combined, clone_items=False)
124+
98125
def to_dict(self) -> Dict[str, Any]:
99126
"""Serializes an :class:`ItemCollection` instance to a JSON-like dictionary."""
100127
return {

tests/test_item_collection.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import json
2-
from pystac.item_collection import ItemCollection
32
from typing import cast
43
import unittest
54
import pystac
@@ -119,6 +118,28 @@ def test_from_relative_path(self) -> None:
119118

120119
def test_from_list_of_dicts(self) -> None:
121120
item_dict = self.stac_io.read_json(self.SIMPLE_ITEM)
122-
item_collection = ItemCollection(items=[item_dict])
121+
item_collection = pystac.ItemCollection(items=[item_dict])
123122

124123
self.assertEqual(item_collection[0].id, item_dict.get("id"))
124+
125+
def test_add_item_collections(self) -> None:
126+
item_1 = pystac.Item.from_file(self.SIMPLE_ITEM)
127+
item_2 = pystac.Item.from_file(self.EXTENDED_ITEM)
128+
item_3 = pystac.Item.from_file(self.CORE_ITEM)
129+
130+
item_collection_1 = pystac.ItemCollection(
131+
items=[item_1, item_2], clone_items=False
132+
)
133+
item_collection_2 = pystac.ItemCollection(
134+
items=[item_2, item_3], clone_items=False
135+
)
136+
137+
combined = item_collection_1 + item_collection_2
138+
139+
self.assertEqual(len(combined), 3)
140+
141+
def test_add_other_raises_error(self) -> None:
142+
item_collection = pystac.ItemCollection.from_file(self.ITEM_COLLECTION)
143+
144+
with self.assertRaises(TypeError):
145+
_ = item_collection + 2

0 commit comments

Comments
 (0)