diff --git a/earthaccess/search.py b/earthaccess/search.py index 04e1c7ac..0b54bcfd 100644 --- a/earthaccess/search.py +++ b/earthaccess/search.py @@ -3,6 +3,7 @@ import dateutil.parser as parser import requests + from cmr import CollectionQuery, GranuleQuery from .auth import Auth @@ -10,7 +11,6 @@ from .results import DataCollection, DataGranule from .typing_ import ( Any, - Dict, List, Never, Optional, @@ -54,7 +54,7 @@ def get_results( while more_results: response = requests.get(url, headers=headers, params={"page_size": page_size}) - if cmr_search_after := query.headers.get("cmr-search-after"): + if cmr_search_after := response.headers.get("cmr-search-after"): headers["cmr-search-after"] = cmr_search_after try: diff --git a/poetry.lock b/poetry.lock index 5ca33866..04267629 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiobotocore" @@ -3084,8 +3084,8 @@ files = [ [package.dependencies] numpy = [ {version = ">=1.20.3", markers = "python_version < \"3.10\""}, - {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -3850,6 +3850,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -3857,8 +3858,16 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -3875,6 +3884,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -3882,6 +3892,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -5109,4 +5120,4 @@ kerchunk = ["dask", "kerchunk"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" -content-hash = "5344a948e7ae73de6bcfd7fa30089469daf6b232e3f0498cc1a47ba860ebb497" +content-hash = "9f38ee827a93f83af0b7b666499b649afa30d6c18e153fea048e0140dbe1e7eb" diff --git a/pyproject.toml b/pyproject.toml index fdc461ea..14498143 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -110,6 +110,7 @@ module = [ "pqdm.*", "s3fs", "tinynetrc.*", # TODO: generate stubs for tinynetrc and remove this line + "vcr.unittest", # TODO: generate stubs for vcr and remove this line ] ignore_missing_imports = true diff --git a/tests/unit/fixtures/vcr_cassettes/PODAAC.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_collections_less_than_2k.yaml similarity index 100% rename from tests/unit/fixtures/vcr_cassettes/PODAAC.yaml rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_collections_less_than_2k.yaml diff --git a/tests/unit/fixtures/vcr_cassettes/ALL.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_collections_more_than_2k.yaml similarity index 100% rename from tests/unit/fixtures/vcr_cassettes/ALL.yaml rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_collections_more_than_2k.yaml diff --git a/tests/unit/fixtures/vcr_cassettes/TestResults.test_data_links.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_data_links.yaml new file mode 100644 index 00000000..1b9e08ac --- /dev/null +++ b/tests/unit/fixtures/vcr_cassettes/TestResults.test_data_links.yaml @@ -0,0 +1,466 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Connection: + - keep-alive + method: GET + uri: https://urs.earthdata.nasa.gov/api/users/tokens + response: + body: + string: '[{"access_token":"eyJ0eXAiOiJKV1QiLCJvcmlnaW4iOiJFYXJ0aGRhdGEgTG9naW4iLCJzaWciOiJlZGxqd3RwdWJrZXlfb3BzIiwiYWxnIjoiUlMyNTYifQ.eyJ0eXBlIjoiVXNlciIsInVpZCI6ImRzY2h1Y2siLCJleHAiOjE3MTcyNjM4MTMsImlhdCI6MTcxMjA3OTgxMywiaXNzIjoiRWFydGhkYXRhIExvZ2luIn0.S_tw0-5JNFEv3si07GYVxvQi81QejNAT2Sh2ZIxAwmqr9UqoSmYg2Wp2Jdn3jaWrSVsRgxBXuLD5w7XFeRju2qOtIqovN3XGJ8VnTdvpklr-gTjk_iLq58334Zzbu5ntnqy-QTzPCKvjvqr3GNuIJcp9z7j5rzd3MEUYOFP1xsd8wehGLpBHzT6ZSzCOwdgzE1AufKq9Vd2GqM_5bc3M9cj-gGy2g3m1mP2OB41wiGvPzup79ds4t_gEPkCecm2rplCP4n1hrY6ZQtXshgM6o49J1nkGSJjE0olHcPwEujKE2s1htWZEycI1TCCxrGpx8K1vwEd0lNaekgPUWwdOlA","token_type":"Bearer","expiration_date":"06/01/2024"}]' + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 09 Apr 2024 21:58:55 GMT + ETag: + - W/"61d0ce8df0bc684ac04ce623aea3668c" + Expires: + - Fri, 01 Jan 1990 00:00:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + Vary: + - Accept + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - 28f6c88b-114d-4319-b6a2-0de0f54c9405 + X-Runtime: + - '0.013338' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Connection: + - keep-alive + method: GET + uri: https://urs.earthdata.nasa.gov/api/users/dschuck?client_id=ntD0YGC_SM3Bjs-Tnxd7bg + response: + body: + string: '{"uid":"dschuck","first_name":"Charles","last_name":"Daniels","email_address":"chuck@developmentseed.org","registered_date":" + 2 Apr 2024 17:43:33PM","country":"United States","study_area":"Other","allow_auth_app_emails":true,"user_type":"Application","affiliation":"Commercial","agreed_to_meris_eula":true,"agreed_to_sentinel_eula":true,"email_verified":true,"user_groups":[],"user_authorized_apps":23,"nams_auid":null}' + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Type: + - application/json; charset=utf-8 + Date: + - Tue, 09 Apr 2024 21:58:55 GMT + ETag: + - W/"5d6f0c723c97c730432ca73084995037" + Expires: + - Fri, 01 Jan 1990 00:00:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + Vary: + - Accept + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - c8cf2bd3-731d-4863-8967-1906de679cbc + X-Runtime: + - '0.017383' + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Connection: + - keep-alive + method: GET + uri: https://urs.earthdata.nasa.gov/profile + response: + body: + string: '' + headers: + Cache-Control: + - no-cache + Connection: + - keep-alive + Content-Type: + - text/html; charset=utf-8 + Date: + - Tue, 09 Apr 2024 21:58:55 GMT + Location: + - https://urs.earthdata.nasa.gov/home + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Set-Cookie: + - _urs-gui_session=abd23c587ce267b8c84ef154346028b0; path=/; expires=Wed, 10 + Apr 2024 21:58:55 GMT; HttpOnly + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - b6384698-e18b-4a99-b80c-b0ebe6cb80b7 + X-Runtime: + - '0.008282' + X-XSS-Protection: + - 1; mode=block + status: + code: 302 + message: Found +- request: + body: null + headers: + Accept: + - '*/*' + Connection: + - keep-alive + Cookie: + - _urs-gui_session=abd23c587ce267b8c84ef154346028b0 + method: GET + uri: https://urs.earthdata.nasa.gov/home + response: + body: + string: "\n\n\n\n\n \n + \ \n \n + \ Earthdata Login\n \n \n\n + \ \n \n \n\n \n \n \n \n \n \n\n \n\n \n + \ \n \n\n + \ \n \n + \ \n\n
\n \n + \
\n
\n
\n + \

Earthdata Login

\n Earthdata Login\n
\n \"Three\n \n
\n\n
\n + \ You must be logged in to access this page\n
\n\n\n\n\n\n\n\n\n + \
\n
\n

\n \n + \ \n \n

\n

\n
\n \n \n

\n

\n + \ \n

\n

\n \n

\n \n

\n \n Register\n

\n

\n + \ \n I + don’t remember my username\n
\n + \ I don’t remember my + password\n
\n \n Help\n

\n
\n\n\n
\n
\n

Get + single sign-on access to all your favorite EOSDIS sites

\n Register for a Profile\n
\n
\n \n By clicking the Log In button above, + you are acknowledging that all Earthdata Login applications running in DAACs \n will have + access to my profile information. \n \n
\n
\n

\n \n + \ Protection and maintenance of user profile information is described + in\n NASA's + Web Privacy Policy.\n \n

\n
\n
\n + \

\n \n Protection and maintenance of user profile + information is described in\n NASA's + Web Privacy Policy.\n \n

\n
\n
\n + \ \n US Govt Property. Unauthorized use subject to prosecution. + Use subject to monitoring per\n NPD2810.\n + \ \n
\n
\n \n
\n
\n \n\n \n + \ \n \n + \ \n + \ \n + \ \n\n \n \n + \ \n\n \n \n\n" + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Type: + - text/html; charset=utf-8 + Date: + - Tue, 09 Apr 2024 21:58:55 GMT + ETag: + - W/"7af405988c901d45ff1b80e3d54e85fa" + Expires: + - Fri, 01 Jan 1990 00:00:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Server: + - nginx/1.22.1 + Set-Cookie: + - _urs-gui_session=abd23c587ce267b8c84ef154346028b0; path=/; expires=Wed, 10 + Apr 2024 21:58:55 GMT; HttpOnly + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + Vary: + - Accept + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Request-Id: + - a5f4494f-83d0-40cc-a966-a45d47155163 + X-Runtime: + - '0.012801' + X-XSS-Protection: + - 1; mode=block + content-length: + - '9058' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Connection: + - keep-alive + method: GET + uri: https://cmr.earthdata.nasa.gov/search/granules.umm_json?short_name=SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205&temporal%5B%5D=2020-01-01T00:00:00Z,2022-01-01T00:00:00Z&page_size=0 + response: + body: + string: '{"hits":147,"took":55,"items":[]}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - CMR-Hits, CMR-Request-Id, X-Request-Id, CMR-Scroll-Id, CMR-Search-After, CMR-Timed-Out, + CMR-Shapefile-Original-Point-Count, CMR-Shapefile-Simplified-Point-Count + CMR-Hits: + - '147' + CMR-Request-Id: + - c8f9b01d-a6a3-4809-8a65-e707f30b3d47 + CMR-Took: + - '55' + Connection: + - keep-alive + Content-MD5: + - 376935be7b2a0e96352603908fe0dcd5 + Content-SHA1: + - b02f8a240f36ad8cd6798334ce2455c338e6d55f + Content-Type: + - application/vnd.nasa.cmr.umm_results+json;version=1.6.5; charset=utf-8 + Date: + - Tue, 09 Apr 2024 21:58:56 GMT + Server: + - ServerTokens ProductOnly + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding, User-Agent + Via: + - 1.1 f300b5f0c0ff51593fb31953294424c0.cloudfront.net (CloudFront) + X-Amz-Cf-Id: + - 6UKqbnR1dCiMWGTDKFtLjE_KomjiZXUhp0ICfljulkAzPCeqJgb3cw== + X-Amz-Cf-Pop: + - PHL51-P1 + X-Cache: + - Miss from cloudfront + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Request-Id: + - 6UKqbnR1dCiMWGTDKFtLjE_KomjiZXUhp0ICfljulkAzPCeqJgb3cw== + X-XSS-Protection: + - 1; mode=block + content-length: + - '33' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Connection: + - keep-alive + method: GET + uri: https://cmr.earthdata.nasa.gov/search/granules.umm_json?short_name=SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205&temporal%5B%5D=2020-01-01T00:00:00Z,2022-01-01T00:00:00Z&page_size=1 + response: + body: + string: '{"hits":147,"took":253,"items":[{"meta":{"concept-type":"granule","concept-id":"G2546526969-POCLOUD","revision-id":2,"native-id":"ssh_grids_v2205_2020010212","collection-concept-id":"C2270392799-POCLOUD","provider-id":"POCLOUD","format":"application/vnd.nasa.cmr.umm+json","revision-date":"2023-01-11T00:16:28.862Z"},"umm":{"TemporalExtent":{"RangeDateTime":{"EndingDateTime":"2020-01-02T00:00:00.000Z","BeginningDateTime":"2020-01-02T00:00:00.000Z"}},"MetadataSpecification":{"URL":"https://cdn.earthdata.nasa.gov/umm/granule/v1.6.5","Name":"UMM-G","Version":"1.6.5"},"GranuleUR":"ssh_grids_v2205_2020010212","ProviderDates":[{"Type":"Insert","Date":"2023-01-11T00:16:13.878Z"},{"Type":"Update","Date":"2023-01-11T00:16:13.878Z"}],"SpatialExtent":{"HorizontalSpatialDomain":{"Geometry":{"BoundingRectangles":[{"WestBoundingCoordinate":0.083,"SouthBoundingCoordinate":-79.917,"EastBoundingCoordinate":180,"NorthBoundingCoordinate":79.917},{"WestBoundingCoordinate":-180,"SouthBoundingCoordinate":-79.917,"EastBoundingCoordinate":-0.083,"NorthBoundingCoordinate":79.917}]}}},"DataGranule":{"ArchiveAndDistributionInformation":[{"SizeUnit":"MB","Size":9.246453285217285,"Checksum":{"Value":"9002febf17632e5921eba5b8f62237e6","Algorithm":"MD5"},"SizeInBytes":9695609,"Name":"ssh_grids_v2205_2020010212.nc"},{"SizeUnit":"MB","Size":6.008148193359375E-5,"Checksum":{"Value":"b0c271019f89f876b2d3c0a9c46b8f77","Algorithm":"MD5"},"SizeInBytes":63,"Name":"ssh_grids_v2205_2020010212.nc.md5"}],"DayNightFlag":"Unspecified","ProductionDateTime":"2022-10-30T20:57:22.377Z"},"CollectionReference":{"Version":"2205","ShortName":"SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205"},"RelatedUrls":[{"URL":"https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-public/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc.md5","Description":"Download + ssh_grids_v2205_2020010212.nc.md5","Type":"EXTENDED METADATA"},{"URL":"s3://podaac-ops-cumulus-public/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc.md5","Description":"This + link provides direct download access via S3 to the granule","Type":"EXTENDED + METADATA"},{"URL":"https://archive.podaac.earthdata.nasa.gov/podaac-ops-cumulus-protected/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc","Description":"Download + ssh_grids_v2205_2020010212.nc","Type":"GET DATA"},{"URL":"s3://podaac-ops-cumulus-protected/SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205/ssh_grids_v2205_2020010212.nc","Description":"This + link provides direct download access via S3 to the granule","Type":"GET DATA + VIA DIRECT ACCESS"},{"URL":"https://archive.podaac.earthdata.nasa.gov/s3credentials","Description":"api + endpoint to retrieve temporary credentials valid for same-region direct s3 + access","Type":"VIEW RELATED INFORMATION"},{"URL":"https://opendap.earthdata.nasa.gov/collections/C2270392799-POCLOUD/granules/ssh_grids_v2205_2020010212","Type":"USE + SERVICE API","Subtype":"OPENDAP DATA","Description":"OPeNDAP request URL"}]}}]}' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - CMR-Hits, CMR-Request-Id, X-Request-Id, CMR-Scroll-Id, CMR-Search-After, CMR-Timed-Out, + CMR-Shapefile-Original-Point-Count, CMR-Shapefile-Simplified-Point-Count + CMR-Hits: + - '147' + CMR-Request-Id: + - 59762a2f-23b9-45a2-a99b-be84748be0e5 + CMR-Search-After: + - '["pocloud",1577923200000,2546526969]' + CMR-Took: + - '254' + Connection: + - keep-alive + Content-MD5: + - 53cf1a1f972e393a32e3cd15ec36f700 + Content-SHA1: + - 60c47f03299dda570448eaecfbd8b3ed10f7bd5a + Content-Type: + - application/vnd.nasa.cmr.umm_results+json;version=1.6.5; charset=utf-8 + Date: + - Tue, 09 Apr 2024 21:58:56 GMT + Server: + - ServerTokens ProductOnly + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Transfer-Encoding: + - chunked + Vary: + - Accept-Encoding, User-Agent + Via: + - 1.1 f300b5f0c0ff51593fb31953294424c0.cloudfront.net (CloudFront) + X-Amz-Cf-Id: + - N9NqPFJ1jWMYiNKZDyuZ71_auV8xRiEL-06uHzn3q2PrTU66FCOKFA== + X-Amz-Cf-Pop: + - PHL51-P1 + X-Cache: + - Miss from cloudfront + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Request-Id: + - N9NqPFJ1jWMYiNKZDyuZ71_auV8xRiEL-06uHzn3q2PrTU66FCOKFA== + X-XSS-Protection: + - 1; mode=block + content-length: + - '3092' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/unit/fixtures/vcr_cassettes/MOD02QKM_2000.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get.yaml similarity index 100% rename from tests/unit/fixtures/vcr_cassettes/MOD02QKM_2000.yaml rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get.yaml diff --git a/tests/unit/fixtures/vcr_cassettes/TELLUS_GRAC.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_less_than_2k.yaml similarity index 100% rename from tests/unit/fixtures/vcr_cassettes/TELLUS_GRAC.yaml rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_less_than_2k.yaml diff --git a/tests/unit/fixtures/vcr_cassettes/CYGNSS.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_more_than_2k.yaml similarity index 100% rename from tests/unit/fixtures/vcr_cassettes/CYGNSS.yaml rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get_all_more_than_2k.yaml diff --git a/tests/unit/fixtures/vcr_cassettes/MOD02QKM.yaml b/tests/unit/fixtures/vcr_cassettes/TestResults.test_get_more_than_2000.yaml similarity index 100% rename from tests/unit/fixtures/vcr_cassettes/MOD02QKM.yaml rename to tests/unit/fixtures/vcr_cassettes/TestResults.test_get_more_than_2000.yaml diff --git a/tests/unit/test_results.py b/tests/unit/test_results.py index 06f8256d..2113ada5 100644 --- a/tests/unit/test_results.py +++ b/tests/unit/test_results.py @@ -1,26 +1,15 @@ import logging -import unittest import earthaccess -import vcr from earthaccess.search import DataCollections -my_vcr = vcr.VCR( - record_mode="once", - decode_compressed_response=True, - # Header matching is not set by default, we need that to test the - # search-after functionality is performing correctly. - match_on=["method", "scheme", "host", "port", "path", "query", "headers"], -) +from vcr.unittest import VCRTestCase # type: ignore[import-untyped] logging.basicConfig() -vcr_log = logging.getLogger("vcr") -vcr_log.setLevel(logging.ERROR) +logging.getLogger("vcr").setLevel(logging.ERROR) -headers_to_filters = ["authorization", "Set-Cookie", "User-Agent", "Accept-Encoding"] - -def assert_unique_results(results): +def unique_results(results): """ When we invoke a search request multiple times we want to ensure that we don't get the same results back. This is a one shot test as the results are preserved @@ -30,7 +19,31 @@ def assert_unique_results(results): return len(unique_concept_ids) == len(results) -class TestResults(unittest.TestCase): +class TestResults(VCRTestCase): + def _get_vcr(self, **kwargs): + myvcr = super(TestResults, self)._get_vcr(**kwargs) + myvcr.cassette_library_dir = "tests/unit/fixtures/vcr_cassettes" + myvcr.decode_compressed_response = True + # Header matching is not set by default, we need that to test the + # search-after functionality is performing correctly. + myvcr.match_on = [ + "method", + "scheme", + "host", + "port", + "path", + "query", + "headers", + ] + myvcr.filter_headers = [ + "Accept-Encoding", + "Authorization", + "Set-Cookie", + "User-Agent", + ] + + return myvcr + def test_data_links(self): granules = earthaccess.search_data( short_name="SEA_SURFACE_HEIGHT_ALT_GRIDS_L4_2SATS_5DAY_6THDEG_V_JPL2205", @@ -58,18 +71,12 @@ def test_get_more_than_2000(self): then we expect multiple invocations of a cmr granule search and to not fetch back more results than we ask for """ - with my_vcr.use_cassette( - "tests/unit/fixtures/vcr_cassettes/MOD02QKM.yaml", - filter_headers=headers_to_filters, - ) as cass: - granules = earthaccess.search_data(short_name="MOD02QKM", count=3000) - - self.assertEqual(len(granules), 4000) + granules = earthaccess.search_data(short_name="MOD02QKM", count=3000) - # Assert that we performed one 'hits' search and two 'results' search queries - self.assertEqual(len(cass), 3) - - assert_unique_results(granules) + # Assert that we performed one 'hits' search and two 'results' search queries + self.assertEqual(len(self.cassette), 3) + self.assertEqual(len(granules), 4000) + self.assertTrue(unique_results(granules)) def test_get(self): """ @@ -77,18 +84,12 @@ def test_get(self): to get the maximum no. of granules from a single CMR call (2000) in a single request """ - with my_vcr.use_cassette( - "tests/unit/fixtures/vcr_cassettes/MOD02QKM_2000.yaml", - filter_headers=headers_to_filters, - ) as cass: - granules = earthaccess.search_data(short_name="MOD02QKM", count=2000) - - self.assertEqual(len(granules), 2000) - - # Assert that we performed one 'hits' search and one 'results' search queries - self.assertEqual(len(cass), 2) + granules = earthaccess.search_data(short_name="MOD02QKM", count=2000) - assert_unique_results(granules) + # Assert that we performed one 'hits' search and one 'results' search queries + self.assertEqual(len(self.cassette), 2) + self.assertEqual(len(granules), 2000) + self.assertTrue(unique_results(granules)) def test_get_all_less_than_2k(self): """ @@ -96,20 +97,14 @@ def test_get_all_less_than_2k(self): invocations of a cmr granule search and to not fetch back more results than we ask for """ - with my_vcr.use_cassette( - "tests/unit/fixtures/vcr_cassettes/TELLUS_GRAC.yaml", - filter_headers=headers_to_filters, - ) as cass: - granules = earthaccess.search_data( - short_name="TELLUS_GRAC_L3_JPL_RL06_LND_v04", count=2000 - ) - - self.assertEqual(len(granules), 163) - - # Assert that we performed a hits query and one search results query - self.assertEqual(len(cass), 2) + granules = earthaccess.search_data( + short_name="TELLUS_GRAC_L3_JPL_RL06_LND_v04", count=2000 + ) - assert_unique_results(granules) + # Assert that we performed a hits query and one search results query + self.assertEqual(len(self.cassette), 2) + self.assertEqual(len(granules), 163) + self.assertTrue(unique_results(granules)) def test_get_all_more_than_2k(self): """ @@ -117,20 +112,14 @@ def test_get_all_more_than_2k(self): invocations of a cmr granule search and to not fetch back more results than we ask for """ - with my_vcr.use_cassette( - "tests/unit/fixtures/vcr_cassettes/CYGNSS.yaml", - filter_headers=headers_to_filters, - ) as cass: - granules = earthaccess.search_data( - short_name="CYGNSS_NOAA_L2_SWSP_25KM_V1.2", count=3000 - ) - - self.assertEqual(len(granules), 2520) - - # Assert that we performed a hits query and two search results queries - self.assertEqual(len(cass), 3) + granules = earthaccess.search_data( + short_name="CYGNSS_NOAA_L2_SWSP_25KM_V1.2", count=3000 + ) - assert_unique_results(granules) + # Assert that we performed a hits query and two search results queries + self.assertEqual(len(self.cassette), 3) + self.assertEqual(len(granules), 2520) + self.assertTrue(unique_results(granules)) def test_collections_less_than_2k(self): """ @@ -138,21 +127,14 @@ def test_collections_less_than_2k(self): invocations of a cmr granule search and to not fetch back more results than we ask for """ - with my_vcr.use_cassette( - "tests/unit/fixtures/vcr_cassettes/PODAAC.yaml", - filter_headers=headers_to_filters, - ) as cass: - query = DataCollections().daac("PODAAC").cloud_hosted(True) - collections = query.get(20) - - self.assertEqual(len(collections), 20) - - # Assert that we performed a single search results query - self.assertEqual(len(cass), 1) + query = DataCollections().daac("PODAAC").cloud_hosted(True) + collections = query.get(20) - assert_unique_results(collections) - - self.is_using_search_after(cass) + # Assert that we performed a single search results query + self.assertEqual(len(self.cassette), 1) + self.assertEqual(len(collections), 20) + self.assertTrue(unique_results(collections)) + self.assert_is_using_search_after(self.cassette) def test_collections_more_than_2k(self): """ @@ -160,30 +142,21 @@ def test_collections_more_than_2k(self): invocations of a cmr granule search and to not fetch back more results than we ask for """ - with my_vcr.use_cassette( - "tests/unit/fixtures/vcr_cassettes/ALL.yaml", - filter_headers=headers_to_filters, - ) as cass: - query = DataCollections() - collections = query.get(3000) - - self.assertEqual(len(collections), 4000) - - # Assert that we performed two search results queries - self.assertEqual(len(cass), 2) + query = DataCollections() + collections = query.get(3000) - assert_unique_results(collections) + # Assert that we performed two search results queries + self.assertEqual(len(self.cassette), 2) + self.assertEqual(len(collections), 4000) + self.assertTrue(unique_results(collections)) + self.assert_is_using_search_after(self.cassette) - self.is_using_search_after(cass) - - def is_using_search_after(self, cass): - # Verify the page no. was not used + def assert_is_using_search_after(self, cass): first_request = True + for request in cass.requests: + # Verify the page number was not used self.assertTrue("page_num" not in request.uri) # Verify that Search After was used in all requests except first - if first_request: - self.assertFalse("CMR-Search-After" in request.headers) - else: - self.assertTrue("CMR-Search-After" in request.headers) + self.assertEqual(first_request, "CMR-Search-After" not in request.headers) first_request = False