diff --git a/CHANGELOG.md b/CHANGELOG.md index fef020e9..1e67f6a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- `Client.open` falls back to the `STAC_URL` environment variable if no url is provided as an argument [#48](https://github.com/stac-utils/pystac-client/pull/48) + ## [v0.1.1] - 2021-04-16 ### Added diff --git a/pystac_client/client.py b/pystac_client/client.py index 0fc03c6b..b6099cf3 100644 --- a/pystac_client/client.py +++ b/pystac_client/client.py @@ -1,4 +1,5 @@ from copy import deepcopy +import os from typing import Callable, Optional from urllib.request import Request @@ -75,13 +76,13 @@ def __repr__(self): return ''.format(self.id) @classmethod - def open(cls, url, headers=None): + def open(cls, url=None, headers=None): """Alias for PySTAC's STAC Object `from_file` method Parameters ---------- - url : str - The URL of a STAC Catalog + url : str, optional + The URL of a STAC Catalog. If not specified, this will use the `STAC_URL` environment variable. Returns ------- @@ -89,14 +90,23 @@ def open(cls, url, headers=None): """ import pystac_client.stac_io + if url is None: + url = os.environ.get("STAC_URL") + + if url is None: + raise TypeError( + "'url' must be specified or the 'STAC_URL' environment variable must be set.") + def read_text_method(url): request = Request(url, headers=headers or {}) return pystac_client.stac_io.read_text_method(request) old_read_text_method = STAC_IO.read_text_method STAC_IO.read_text_method = read_text_method - catalog = cls.from_file(url) - STAC_IO.read_text_method = old_read_text_method + try: + catalog = cls.from_file(url) + finally: + STAC_IO.read_text_method = old_read_text_method catalog.headers = headers return catalog diff --git a/tests/cassettes/test_client/TestAPI.test_environment_variable.yaml b/tests/cassettes/test_client/TestAPI.test_environment_variable.yaml new file mode 100644 index 00000000..41ae9ec0 --- /dev/null +++ b/tests/cassettes/test_client/TestAPI.test_environment_variable.yaml @@ -0,0 +1,95 @@ +interactions: +- request: + body: null + headers: + Connection: + - close + Host: + - eod-catalog-svc-prod.astraea.earth + User-Agent: + - Python-urllib/3.9 + method: GET + uri: https://eod-catalog-svc-prod.astraea.earth + response: + body: + string: '{"conformsTo":["http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core","http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30","http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson","http://www.opengis.net/spec/ogcapi_common-2/1.0/req/collections","http://stacspec.org/spec/api/1.0.0-beta.1/core","http://stacspec.org/spec/api/1.0.0-beta.1/req/stac-search","http://stacspec.org/spec/api/1.0.0-beta.1/req/stac-response","http://stacspec.org/spec/api/1.0.0-beta.1/req/fields","http://stacspec.org/spec/api/1.0.0-beta.1/req/context","http://stacspec.org/spec/api/1.0.0-beta.1/req/sort"],"description":"Astraea + Earth OnDemand geospatial imagery query and analysis tool","id":"astraea","links":[{"href":"https://eod-catalog-svc-prod.astraea.earth","rel":"self","title":"Self","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth","rel":"root","title":"Root","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/api","rel":"service-desc","title":"OpenAPI + specification","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/api.html","rel":"service-doc","title":"API + documentation","type":"text/html"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections","rel":"data","title":"Collections","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections","rel":"collections","title":"Collections","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/landsat8_l1tp","rel":"child","title":"Landsat + 8 C1 T1","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/mcd43a4","rel":"child","title":"MCD43A4 + NBAR","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/mod11a1","rel":"child","title":"MOD11A1 + LST","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/myd11a1","rel":"child","title":"MYD11A1 + LST","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/mod13a1","rel":"child","title":"MOD13A1 + VI","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/myd13a1","rel":"child","title":"MYD13A1 + VI","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/sentinel1_l1c_grd","rel":"child","title":"Sentinel-1 + L1C GRD","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/sentinel2_l2a","rel":"child","title":"Sentinel-2 + L2A","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/sentinel2_l1c","rel":"child","title":"Sentinel-2 + L1C","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/naip","rel":"child","title":"NAIP","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/maxar_open_data","rel":"child","title":"Maxar + Open Data","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/collections/spacenet7","rel":"child","title":"SpaceNet + 7","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/aggregate","rel":"aggregation","title":"Aggregation","type":"application/json"},{"capabilities":{"parameters":[{"name":"composite","values":[{"description":"Default + View.","name":"default","title":"Default View"},{"description":"True Color + Composite.","name":"true_color","title":"True Color Composite"},{"description":"Normalized + Difference Vegetation Index.","name":"ndvi","title":"NDVI"},{"description":"Normalized + Difference Water Index using Green and NIR per McFeeters(1997).","name":"ndwi","title":"NDWI + (Green & NIR)"},{"description":"Normalized Difference Water Index using NIR + and SWIR per Gao(1997).","name":"ndwi2","title":"NDWI (NIR & SWIR)"},{"description":"Color + Infrared (Vegetation) consisting of Near-infrared, Red, and Green bands.","name":"color_infrared_veg1","title":"Color + Infrared Vegetation (NRG)"},{"description":"Color Infrared (Vegetation) consisting + of Near-infrared, Green, and Blue bands.","name":"color_infrared_veg2","title":"Color + Infrared Vegetation 2 (NGB)"},{"description":"False Color Infrared (Urban).","name":"false_color_urban","title":"False + Color (Urban)"},{"description":"Agriculture.","name":"agriculture","title":"Agriculture"},{"description":"Moisture + Index.","name":"moisture_index","title":"Moisture Index"},{"description":"Geology.","name":"geology","title":"Geology"},{"description":"Bathymetric.","name":"bathymetric","title":"Bathymetric"},{"description":"Atmospheric + Penetration.","name":"atmospheric_penetration","title":"Atmospheric Penetration"},{"description":"SWIR + 1.","name":"swir1","title":"SWIR 1"},{"description":"SWIR 2.","name":"swir2","title":"SWIR + 2"},{"description":"SAR VV Polarization.","name":"sar_vv","title":"SAR VV + Polarization"},{"description":"SAR VH Polarization.","name":"sar_vh","title":"SAR + VH Polarization"},{"description":"SAR HH Polarization.","name":"sar_hh","title":"SAR + HH Polarization"},{"description":"SAR HV Polarization.","name":"sar_hv","title":"SAR + HV Polarization"},{"description":"SAR False Color (Urban).","name":"sar_false_color_urban","title":"SAR + False Color (Urban)"}]}]},"href":"https://eod-catalog-svc-prod.astraea.earth/aggregate","rel":"aggregate","title":"Aggregate","type":"application/json"},{"capabilities":{"parameters":[{"name":"composite","values":[{"description":"Default + View.","name":"default","title":"Default View"},{"description":"True Color + Composite.","name":"true_color","title":"True Color Composite"},{"description":"Normalized + Difference Vegetation Index.","name":"ndvi","title":"NDVI"},{"description":"Normalized + Difference Water Index using Green and NIR per McFeeters(1997).","name":"ndwi","title":"NDWI + (Green & NIR)"},{"description":"Normalized Difference Water Index using NIR + and SWIR per Gao(1997).","name":"ndwi2","title":"NDWI (NIR & SWIR)"},{"description":"Color + Infrared (Vegetation) consisting of Near-infrared, Red, and Green bands.","name":"color_infrared_veg1","title":"Color + Infrared Vegetation (NRG)"},{"description":"Color Infrared (Vegetation) consisting + of Near-infrared, Green, and Blue bands.","name":"color_infrared_veg2","title":"Color + Infrared Vegetation 2 (NGB)"},{"description":"False Color Infrared (Urban).","name":"false_color_urban","title":"False + Color (Urban)"},{"description":"Agriculture.","name":"agriculture","title":"Agriculture"},{"description":"Moisture + Index.","name":"moisture_index","title":"Moisture Index"},{"description":"Geology.","name":"geology","title":"Geology"},{"description":"Bathymetric.","name":"bathymetric","title":"Bathymetric"},{"description":"Atmospheric + Penetration.","name":"atmospheric_penetration","title":"Atmospheric Penetration"},{"description":"SWIR + 1.","name":"swir1","title":"SWIR 1"},{"description":"SWIR 2.","name":"swir2","title":"SWIR + 2"},{"description":"SAR VV Polarization.","name":"sar_vv","title":"SAR VV + Polarization"},{"description":"SAR VH Polarization.","name":"sar_vh","title":"SAR + VH Polarization"},{"description":"SAR HH Polarization.","name":"sar_hh","title":"SAR + HH Polarization"},{"description":"SAR HV Polarization.","name":"sar_hv","title":"SAR + HV Polarization"},{"description":"SAR False Color (Urban).","name":"sar_false_color_urban","title":"SAR + False Color (Urban)"}]}]},"href":"https://eod-catalog-svc-prod.astraea.earth/search","rel":"search","title":"Search","type":"application/json"},{"href":"https://eod-catalog-svc-prod.astraea.earth/grid_id_definitions?20200218","rel":"grid_id_definitions","title":"Grid + ID Definitions","type":"application/json"}],"stac_extensions":["eo","proj","context"],"stac_version":"1.0.0-beta.2","title":"Astraea + Earth OnDemand"}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-Astraea-Catalog-Client + - Authorization, Content-Type, X-Requested-With + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - no-cache, no-store, must-revalidate + Connection: + - close + Content-Length: + - '7768' + Content-Type: + - application/json + Date: + - Mon, 03 May 2021 15:27:20 GMT + Server: + - akka-http/10.2.3 + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_client.py b/tests/test_client.py index 66aeca3d..c685411d 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,4 +1,5 @@ from datetime import datetime +import os from dateutil.tz import tzutc import pystac @@ -96,6 +97,30 @@ def test_from_file(self): assert api.title == 'Astraea Earth OnDemand' + @pytest.mark.vcr + def test_environment_variable(self): + old_stac_url = os.environ.get("STAC_URL") + os.environ["STAC_URL"] = ASTRAEA_URL + try: + client = Client.open() + assert client.title == "Astraea Earth OnDemand" + finally: + if old_stac_url: + os.environ["STAC_URL"] = old_stac_url + else: + del os.environ["STAC_URL"] + + def test_no_url(self): + old_stac_url = os.environ.get("STAC_URL") + if old_stac_url: + del os.environ["STAC_URL"] + try: + with pytest.raises(TypeError): + Client.open() + finally: + if old_stac_url: + os.environ["STAC_URL"] = old_stac_url + class TestAPISearch: @pytest.fixture(scope='function')