| 
19 | 19 |     Collection,  | 
20 | 20 |     Extent,  | 
21 | 21 |     Item,  | 
 | 22 | +    ItemCollection,  | 
22 | 23 |     Provider,  | 
23 | 24 |     SpatialExtent,  | 
24 | 25 |     TemporalExtent,  | 
@@ -711,3 +712,111 @@ def test_permissive_temporal_extent_deserialization(collection: Collection) -> N  | 
711 | 712 |     ]["interval"][0]  | 
712 | 713 |     with pytest.warns(UserWarning):  | 
713 | 714 |         Collection.from_dict(collection_dict)  | 
 | 715 | + | 
 | 716 | + | 
 | 717 | +@pytest.mark.parametrize("fixture_name", ("sample_item_collection", "sample_items"))  | 
 | 718 | +def test_from_items(fixture_name: str, request: pytest.FixtureRequest) -> None:  | 
 | 719 | +    items = request.getfixturevalue(fixture_name)  | 
 | 720 | +    collection = Collection.from_items(items)  | 
 | 721 | + | 
 | 722 | +    for item in items:  | 
 | 723 | +        assert collection.id == item.collection_id  | 
 | 724 | +        assert collection.extent.spatial.bboxes[0][0] <= item.bbox[0]  | 
 | 725 | +        assert collection.extent.spatial.bboxes[0][1] <= item.bbox[1]  | 
 | 726 | +        assert collection.extent.spatial.bboxes[0][2] >= item.bbox[2]  | 
 | 727 | +        assert collection.extent.spatial.bboxes[0][3] >= item.bbox[3]  | 
 | 728 | + | 
 | 729 | +        start = collection.extent.temporal.intervals[0][0]  | 
 | 730 | +        end = collection.extent.temporal.intervals[0][1]  | 
 | 731 | +        assert start and start <= str_to_datetime(item.properties["start_datetime"])  | 
 | 732 | +        assert end and end >= str_to_datetime(item.properties["end_datetime"])  | 
 | 733 | + | 
 | 734 | +    if isinstance(items, ItemCollection):  | 
 | 735 | +        expected = {(link["rel"], link["href"]) for link in items.extra_fields["links"]}  | 
 | 736 | +        actual = {(link.rel, link.href) for link in collection.links}  | 
 | 737 | +        assert expected.issubset(actual)  | 
 | 738 | + | 
 | 739 | + | 
 | 740 | +def test_from_items_pulls_from_properties() -> None:  | 
 | 741 | +    item1 = Item(  | 
 | 742 | +        id="test-item-1",  | 
 | 743 | +        geometry=ARBITRARY_GEOM,  | 
 | 744 | +        bbox=[-10, -20, 0, -10],  | 
 | 745 | +        datetime=datetime(2000, 2, 1, 12, 0, 0, 0, tzinfo=tz.UTC),  | 
 | 746 | +        collection="test-collection-1",  | 
 | 747 | +        properties={"title": "Test Item", "description": "Extra words describing"},  | 
 | 748 | +    )  | 
 | 749 | +    collection = Collection.from_items([item1])  | 
 | 750 | +    assert collection.id == item1.collection_id  | 
 | 751 | +    assert collection.title == item1.properties["title"]  | 
 | 752 | +    assert collection.description == item1.properties["description"]  | 
 | 753 | + | 
 | 754 | + | 
 | 755 | +def test_from_items_without_collection_id() -> None:  | 
 | 756 | +    item1 = Item(  | 
 | 757 | +        id="test-item-1",  | 
 | 758 | +        geometry=ARBITRARY_GEOM,  | 
 | 759 | +        bbox=[-10, -20, 0, -10],  | 
 | 760 | +        datetime=datetime(2000, 2, 1, 12, 0, 0, 0, tzinfo=tz.UTC),  | 
 | 761 | +        properties={},  | 
 | 762 | +    )  | 
 | 763 | +    with pytest.raises(ValueError, match="Collection id must be defined."):  | 
 | 764 | +        Collection.from_items([item1])  | 
 | 765 | + | 
 | 766 | +    collection = Collection.from_items([item1], id="test-collection")  | 
 | 767 | +    assert collection.id == "test-collection"  | 
 | 768 | + | 
 | 769 | + | 
 | 770 | +def test_from_items_with_collection_ids() -> None:  | 
 | 771 | +    item1 = Item(  | 
 | 772 | +        id="test-item-1",  | 
 | 773 | +        geometry=ARBITRARY_GEOM,  | 
 | 774 | +        bbox=[-10, -20, 0, -10],  | 
 | 775 | +        datetime=datetime(2000, 2, 1, 12, 0, 0, 0, tzinfo=tz.UTC),  | 
 | 776 | +        collection="test-collection-1",  | 
 | 777 | +        properties={},  | 
 | 778 | +    )  | 
 | 779 | +    item2 = Item(  | 
 | 780 | +        id="test-item-2",  | 
 | 781 | +        geometry=ARBITRARY_GEOM,  | 
 | 782 | +        bbox=[-15, -20, 0, -10],  | 
 | 783 | +        datetime=datetime(2000, 2, 1, 13, 0, 0, 0, tzinfo=tz.UTC),  | 
 | 784 | +        collection="test-collection-2",  | 
 | 785 | +        properties={},  | 
 | 786 | +    )  | 
 | 787 | + | 
 | 788 | +    with pytest.raises(ValueError, match="Collection id must be defined."):  | 
 | 789 | +        Collection.from_items([item1, item2])  | 
 | 790 | + | 
 | 791 | +    collection = Collection.from_items([item1, item2], id="test-collection")  | 
 | 792 | +    assert collection.id == "test-collection"  | 
 | 793 | + | 
 | 794 | + | 
 | 795 | +def test_from_items_with_different_values() -> None:  | 
 | 796 | +    item1 = Item(  | 
 | 797 | +        id="test-item-1",  | 
 | 798 | +        geometry=ARBITRARY_GEOM,  | 
 | 799 | +        bbox=[-10, -20, 0, -10],  | 
 | 800 | +        datetime=datetime(2000, 2, 1, 12, 0, 0, 0, tzinfo=tz.UTC),  | 
 | 801 | +        properties={"title": "Test Item 1"},  | 
 | 802 | +    )  | 
 | 803 | +    item2 = Item(  | 
 | 804 | +        id="test-item-2",  | 
 | 805 | +        geometry=ARBITRARY_GEOM,  | 
 | 806 | +        bbox=[-15, -20, 0, -10],  | 
 | 807 | +        datetime=datetime(2000, 2, 1, 13, 0, 0, 0, tzinfo=tz.UTC),  | 
 | 808 | +        properties={"title": "Test Item 2"},  | 
 | 809 | +    )  | 
 | 810 | + | 
 | 811 | +    collection = Collection.from_items([item1, item2], id="test_collection")  | 
 | 812 | +    assert collection.title is None  | 
 | 813 | + | 
 | 814 | + | 
 | 815 | +def test_from_items_with_providers(sample_item_collection: ItemCollection) -> None:  | 
 | 816 | +    sample_item_collection.extra_fields["providers"] = [{"name": "pystac"}]  | 
 | 817 | + | 
 | 818 | +    collection = Collection.from_items(sample_item_collection)  | 
 | 819 | +    assert collection.providers and len(collection.providers) == 1  | 
 | 820 | + | 
 | 821 | +    provider = collection.providers[0]  | 
 | 822 | +    assert provider and provider.name == "pystac"  | 
0 commit comments