|  | 
| 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