Example #1
0
def test_app_sort_extension(load_test_data, app_client, postgres_transactions):
    first_item = load_test_data("test_item.json")
    item_date = datetime.strptime(first_item["properties"]["datetime"],
                                  "%Y-%m-%dT%H:%M:%SZ")
    postgres_transactions.create_item(Item.parse_obj(first_item),
                                      request=MockStarletteRequest)

    second_item = load_test_data("test_item.json")
    second_item["id"] = "another-item"
    another_item_date = item_date - timedelta(days=1)
    second_item["properties"]["datetime"] = another_item_date.strftime(
        "%Y-%m-%dT%H:%M:%SZ")
    postgres_transactions.create_item(Item.parse_obj(second_item),
                                      request=MockStarletteRequest)

    params = {
        "collections": [first_item["collection"]],
        "sortby": [{
            "field": "datetime",
            "direction": "desc"
        }],
    }
    resp = app_client.post("/search", json=params)
    assert resp.status_code == 200
    resp_json = resp.json()
    assert resp_json["features"][0]["id"] == first_item["id"]
    assert resp_json["features"][1]["id"] == second_item["id"]
def test_fields_filter():
    fields = FieldsExtension(includes={"id", "geometry", "properties.foo"},
                             excludes={"properties.bar"})

    item = Item(
        id="test-fields-filter",
        geometry=Polygon.from_bounds(0, 0, 0, 0),
        properties={
            "datetime": datetime.utcnow(),
            "foo": "foo",
            "bar": "bar"
        },
        assets={},
        links=[],
        bbox=[0, 0, 0, 0],
    )

    d = item.to_dict(**fields.filter)
    assert d.pop("id") == item.id
    assert d.pop("geometry") == item.geometry
    props = d.pop("properties")
    assert props["foo"] == "foo"

    assert not props.get("bar")
    assert not d
Example #3
0
async def test_fetches_valid_item(app_client, load_test_data: Callable,
                                  load_test_collection):
    coll = load_test_collection

    in_json = load_test_data("test_item.json")
    in_item = Item.parse_obj(in_json)
    resp = await app_client.post(
        "/collections/{coll.id}/items",
        json=in_json,
    )
    assert resp.status_code == 200

    post_item = Item.parse_obj(resp.json())
    assert in_item.dict(exclude={"links"}) == post_item.dict(exclude={"links"})

    resp = await app_client.get(f"/collections/{coll.id}/items/{post_item.id}")

    assert resp.status_code == 200
    item_dict = resp.json()
    # Mock root to allow validation
    mock_root = pystac.Catalog(id="test",
                               description="test desc",
                               href="https://example.com")
    item = pystac.Item.from_dict(item_dict,
                                 preserve_dict=False,
                                 root=mock_root)
    item.validate()
def test_invalid_geometry():
    test_item = request(EO_EXTENSION)

    # Remove the last coordinate
    test_item["geometry"]["coordinates"][0].pop(-1)

    with pytest.raises(ValidationError) as e:
        Item(**test_item)
def main(scene_list, wrs2_grid, collection, level):
    """Create Landsat STAC Items."""
    # Create items
    for item in create_stac_items(scene_list,
                                  wrs2_grid,
                                  collection=collection,
                                  level=level):
        click.echo(Item(**item).json(exclude_none=True))
Example #6
0
async def test_create_item_conflict(app_client, load_test_data: Callable,
                                    load_test_collection):
    pass

    in_json = load_test_data("test_item.json")
    Item.parse_obj(in_json)
    resp = await app_client.post(
        "/collections/{coll.id}/items",
        json=in_json,
    )
    assert resp.status_code == 200

    resp = await app_client.post(
        "/collections/{coll.id}/items",
        json=in_json,
    )
    assert resp.status_code == 409
def test_asset_extras():
    test_item = request(EO_EXTENSION)
    for asset in test_item["assets"]:
        test_item["assets"][asset]["foo"] = "bar"

    item = Item(**test_item)
    for (asset_name, asset) in item.assets.items():
        assert asset.foo == "bar"
Example #8
0
async def load_test_item(app_client, load_test_data, load_test_collection):
    data = load_test_data("test_item.json")
    resp = await app_client.post(
        "/collections/{coll.id}/items",
        json=data,
    )
    assert resp.status_code == 200
    return Item.parse_obj(resp.json())
Example #9
0
    async def _search_base(self, search_request: PgstacSearch,
                           **kwargs) -> Dict[str, Any]:
        """Cross catalog search (POST).

        Called with `POST /search`.

        Args:
            search_request: search request parameters.

        Returns:
            ItemCollection containing items which match the search criteria.
        """
        request = kwargs["request"]
        pool = request.app.state.readpool

        # pool = kwargs["request"].app.state.readpool
        req = search_request.json(exclude_none=True)

        async with pool.acquire() as conn:
            q, p = render(
                """
                SELECT * FROM search(:req::text::jsonb);
                """,
                req=req,
            )
            items = await conn.fetchval(q, *p)
        next = items.pop("next", None)
        prev = items.pop("prev", None)
        collection = ItemCollection.construct(**items)
        cleaned_features = []
        if collection.features is None or len(collection.features) == 0:
            raise NotFoundError("No features found")

        for feature in collection.features:
            feature = Item.construct(**feature)
            if "links" not in search_request.fields.exclude:
                links = await ItemLinks(
                    collection_id=feature.collection,
                    item_id=feature.id,
                    request=request,
                ).get_links()
                feature.links = links
                exclude = search_request.fields.exclude
                if len(exclude) == 0:
                    exclude = None
                include = search_request.fields.include
                if len(include) == 0:
                    include = None
                feature = feature.dict(exclude_none=True, )
            cleaned_features.append(feature)
            collection.features = cleaned_features
        collection.links = await PagingLinks(
            request=request,
            next=next,
            prev=prev,
        ).get_links()
        return collection
Example #10
0
def test_create_duplicate_item_different_collections(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    # create test-collection
    coll = load_test_data("test_collection.json")
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    # create test-collection-2
    coll["id"] = "test-collection-2"
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    # add item to test-collection
    item = load_test_data("test_item.json")
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    # get item from test-collection
    resp = postgres_core.get_item(item["id"],
                                  item["collection"],
                                  request=MockStarletteRequest)
    assert Item(**item).dict(exclude={
        "links":...,
        "properties": {"created", "updated"}
    }) == Item(**resp).dict(exclude={
        "links":...,
        "properties": {"created", "updated"}
    })

    # add item to test-collection-2
    item["collection"] = "test-collection-2"
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    # get item with same id from test-collection-2
    resp = postgres_core.get_item(item["id"],
                                  item["collection"],
                                  request=MockStarletteRequest)
    assert Item(**item).dict(exclude={
        "links":...,
        "properties": {"created", "updated"}
    }) == Item(**resp).dict(exclude={
        "links":...,
        "properties": {"created", "updated"}
    })
Example #11
0
async def test_create_item(app_client, load_test_data: Callable, load_test_collection):
    coll = load_test_collection

    in_json = load_test_data("test_item.json")
    in_item = Item.parse_obj(in_json)
    resp = await app_client.post(
        "/collections/{coll.id}/items",
        json=in_json,
    )
    assert resp.status_code == 200

    post_item = Item.parse_obj(resp.json())
    assert in_item.dict(exclude={"links"}) == post_item.dict(exclude={"links"})

    resp = await app_client.get(f"/collections/{coll.id}/items/{post_item.id}")

    assert resp.status_code == 200
    get_item = Item.parse_obj(resp.json())
    assert in_item.dict(exclude={"links"}) == get_item.dict(exclude={"links"})
Example #12
0
def test_create_item(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    coll = load_test_data("test_collection.json")
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)
    item = load_test_data("test_item.json")
    postgres_transactions.create_item(item, request=MockStarletteRequest)
    resp = postgres_core.get_item(item["id"],
                                  item["collection"],
                                  request=MockStarletteRequest)
    assert Item(**item).dict(exclude={
        "links":...,
        "properties": {"created", "updated"}
    }) == Item(**resp).dict(exclude={
        "links":...,
        "properties": {"created", "updated"}
    })
Example #13
0
def test_app_fields_extension(load_test_data, app_client,
                              postgres_transactions):
    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    resp = app_client.get("/search",
                          params={"collections": ["test-collection"]})
    assert resp.status_code == 200
    resp_json = resp.json()
    assert list(resp_json["features"][0]["properties"]) == ["datetime"]
Example #14
0
def test_app_context_extension(load_test_data, app_client,
                               postgres_transactions):
    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    resp = app_client.get("/search",
                          params={"collections": ["test-collection"]})
    assert resp.status_code == 200
    resp_json = resp.json()
    assert "context" in resp_json
    assert resp_json["context"]["returned"] == resp_json["context"][
        "matched"] == 1
Example #15
0
def validate_item(infile):
    """Validate stac item"""
    r = requests.get(infile)
    r.raise_for_status()
    stac_item = r.json()
    try:
        item = Item(**stac_item)
        validate_extensions(item, reraise_exception=True)
    except ValidationError as e:
        click.echo(str(e))
        return
    click.echo(f"{infile} is valid")
    return
Example #16
0
def test_create_item_already_exists(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    with pytest.raises(ConflictError):
        postgres_transactions.create_item(item, request=MockStarletteRequest)
Example #17
0
def test_create_item(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)
    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)
    resp = postgres_core.get_item(
        item.id, item.collection, request=MockStarletteRequest
    )
    assert item.dict(
        exclude={"links": ..., "properties": {"created", "updated"}}
    ) == resp.dict(exclude={"links": ..., "properties": {"created", "updated"}})
Example #18
0
async def test_update_item(app_client, load_test_collection, load_test_item):
    coll = load_test_collection
    item = load_test_item

    item.properties.description = "Update Test"

    resp = await app_client.put(f"/collections/{coll.id}/items", json=item.dict())
    assert resp.status_code == 200

    resp = await app_client.get(f"/collections/{coll.id}/items/{item.id}")
    assert resp.status_code == 200

    get_item = Item.parse_obj(resp.json())
    assert item.dict(exclude={"links"}) == get_item.dict(exclude={"links"})
    assert get_item.properties.description == "Update Test"
Example #19
0
def test_delete_item(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    postgres_transactions.delete_item(item.id, request=MockStarletteRequest)

    with pytest.raises(NotFoundError):
        postgres_core.get_item(item.id, request=MockStarletteRequest)
Example #20
0
def test_update_item(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    item.properties.foo = "bar"
    postgres_transactions.update_item(item, request=MockStarletteRequest)

    updated_item = postgres_core.get_item(item.id,
                                          request=MockStarletteRequest)
    assert updated_item.properties.foo == "bar"
Example #21
0
def test_app_query_extension(load_test_data, app_client,
                             postgres_transactions):
    test_item = load_test_data("test_item.json")
    item = Item.parse_obj(test_item)
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    params = {
        "query": {
            "proj:epsg": {
                "gt": test_item["properties"]["proj:epsg"] + 1
            }
        }
    }
    resp = app_client.post("/search", json=params)
    assert resp.status_code == 200
    resp_json = resp.json()
    assert len(resp_json["features"]) == 0
Example #22
0
def test_get_collection_items(
    postgres_core: CoreCrudClient,
    postgres_transactions: TransactionsClient,
    load_test_data: Callable,
):
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    item = Item.parse_obj(load_test_data("test_item.json"))

    for _ in range(5):
        item.id = str(uuid.uuid4())
        postgres_transactions.create_item(item, request=MockStarletteRequest)

    fc = postgres_core.item_collection(coll.id, request=MockStarletteRequest)
    assert len(fc.features) == 5

    for item in fc.features:
        assert item.collection == coll.id
def tiles_extension_app(postgres_core, postgres_transactions, load_test_data):
    # Ingest test data for testing
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    item = Item.parse_obj(load_test_data("test_item.json"))
    postgres_transactions.create_item(item, request=MockStarletteRequest)

    settings = SqlalchemySettings()
    api = StacApi(
        settings=settings,
        client=postgres_core,
        extensions=[TilesExtension(TilesClient(postgres_core))],
    )
    with TestClient(api.app) as test_app:
        yield test_app

    # Cleanup test data
    postgres_transactions.delete_item(item.id, request=MockStarletteRequest)
    postgres_transactions.delete_collection(coll.id,
                                            request=MockStarletteRequest)
Example #24
0
def test_bulk_item_insert(
    postgres_transactions: TransactionsClient,
    postgres_bulk_transactions: BulkTransactionsClient,
    load_test_data: Callable,
):
    coll = Collection.parse_obj(load_test_data("test_collection.json"))
    postgres_transactions.create_collection(coll, request=MockStarletteRequest)

    item = Item.parse_obj(load_test_data("test_item.json"))

    items = []
    for _ in range(10):
        _item = item.dict()
        _item["id"] = str(uuid.uuid4())
        items.append(_item)

    postgres_bulk_transactions.bulk_item_insert(Items(items=items))

    for item in items:
        postgres_transactions.delete_item(item["id"],
                                          request=MockStarletteRequest)
Example #25
0
def test_item_to_json():
    test_item = request(EO_EXTENSION)
    item = Item(**test_item)
    assert item.to_json() == json.dumps(item.to_dict())
def test_item_to_json():
    test_item = request(EO_EXTENSION)
    item = Item(**test_item)
    dict_match(json.loads(item.to_json()), item.to_dict())
def test_label_extension_validation_error():
    test_item = request(LABEL_EXTENSION)
    test_item["properties"]["label:type"] = "invalid-label-type"

    with pytest.raises(ValidationError):
        Item(**test_item)
def test_single_file_stac_validation_error():
    test_item = request(SINGLE_FILE_STAC)
    del test_item["collections"]

    with pytest.raises(ValidationError):
        Item(**test_item)
def test_geo_interface():
    test_item = request(EO_EXTENSION)
    item = Item(**test_item)
    geom = shape(item.geometry)
    test_item["geometry"] = geom
    Item(**test_item)
Example #30
0
async def test_pagination(app_client, load_test_data, load_test_collection):
    """Test item collection pagination (paging extension)"""
    coll = load_test_collection
    item_count = 21
    test_item = load_test_data("test_item.json")

    for idx in range(1, item_count):
        item = Item.parse_obj(test_item)
        item.id = item.id + str(idx)
        item.properties.datetime = f"2020-01-{idx:02d}T00:00:00"
        resp = await app_client.post(f"/collections/{coll.id}/items",
                                     json=item.dict())
        assert resp.status_code == 200

    resp = await app_client.get(f"/collections/{coll.id}/items",
                                params={"limit": 3})
    assert resp.status_code == 200
    first_page = resp.json()
    for feature in first_page["features"]:
        print(feature["id"], feature["properties"]["datetime"])
    print(f"first page links {first_page['links']}")
    assert len(first_page["features"]) == 3

    nextlink = [
        link["href"] for link in first_page["links"] if link["rel"] == "next"
    ].pop()

    assert nextlink is not None

    assert [f["id"] for f in first_page["features"]] == [
        "test-item20",
        "test-item19",
        "test-item18",
    ]

    print(f"Next {nextlink}")

    resp = await app_client.get(nextlink)
    assert resp.status_code == 200
    second_page = resp.json()
    for feature in second_page["features"]:
        print(feature["id"], feature["properties"]["datetime"])
    print(f"second page links {second_page['links']}")
    assert len(first_page["features"]) == 3

    nextlink = [
        link["href"] for link in second_page["links"] if link["rel"] == "next"
    ].pop()

    assert nextlink is not None

    prevlink = [
        link["href"] for link in second_page["links"]
        if link["rel"] == "previous"
    ].pop()

    assert prevlink is not None
    print(nextlink, prevlink)

    assert [f["id"] for f in second_page["features"]] == [
        "test-item17",
        "test-item16",
        "test-item15",
    ]

    resp = await app_client.get(prevlink)
    assert resp.status_code == 200
    back_page = resp.json()
    for feature in back_page["features"]:
        print(feature["id"], feature["properties"]["datetime"])
    print(back_page["links"])
    assert len(back_page["features"]) == 3
    assert [f["id"] for f in back_page["features"]] == [
        "test-item20",
        "test-item19",
        "test-item18",
    ]