Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/check-links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ jobs:
^https://asdc\.larc\.nasa\.gov/project/TEMPO
^https://www\.jpl\.nasa\.gov/missions/surface-water-and-ocean-topography-swot/
^https://wiki\.esipfed\.org/FUNding_Friday_Projects
^https://x\.com/.*
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [Unreleased]

### Breaking changes

- Renamed the query classes `DataCollections`, `DataGranules`, and
`DataServices` to `DataCollectionsQuery`, `DataGranulesQuery`, and
`DataServicesQuery`.
([#1363](https://github.com/earthaccess-dev/earthaccess/issues/1363))
([@Sherwin-14](https://github.com/Sherwin-14))

## [v0.19.0] - 2026-09-03

### Breaking changes
Expand Down
6 changes: 3 additions & 3 deletions docs/api/collections/collections-query.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Documentation for `DataCollections`
# Documentation for `DataCollectionsQuery`

### DataCollections is the class `earthaccess` uses to query CMR at the **dataset** level.
### DataCollectionsQuery is the class `earthaccess` uses to query CMR at the **dataset** level.

::: earthaccess.search.DataCollections
::: earthaccess.search.DataCollectionsQuery
options:
show_source: false
inherited_members: true
Expand Down
2 changes: 1 addition & 1 deletion docs/api/collections/collections-services.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Documentation for `Collection Services`

::: earthaccess.DataServices
::: earthaccess.DataServicesQuery
options:
inherited_members: true
show_root_heading: true
Expand Down
6 changes: 3 additions & 3 deletions docs/api/granules/granules-query.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Documentation for `Granules`
# Documentation for `DataGranulesQuery`


### DataGranules is the class `earthaccess` uses to query CMR at the **granule** level.
### DataGranulesQuery is the class `earthaccess` uses to query CMR at the **granule** level.

::: earthaccess.search.DataGranules
::: earthaccess.search.DataGranulesQuery
options:
inherited_members: true
show_root_heading: true
Expand Down
22 changes: 11 additions & 11 deletions docs/user/tutorials/restricted-datasets.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"metadata": {},
"outputs": [],
"source": [
"from earthaccess import Auth, DataCollections, DataGranules, Store\n",
"from earthaccess import Auth, DataCollectionsQuery, DataGranulesQuery, Store\n",
"\n",
"auth = Auth()"
]
Expand Down Expand Up @@ -83,19 +83,19 @@
"\n",
"```python\n",
"# An anonymous query to CMR\n",
"Query = DataCollections().keyword('elevation')\n",
"Query = DataCollectionsQuery().keyword('elevation')\n",
"# An authenticated query to CMR\n",
"Query = DataCollections(auth).keyword('elevation')\n",
"Query = DataCollectionsQuery(auth).keyword('elevation')\n",
"```\n",
"\n",
"and it's the same with DataGranules\n",
"and it's the same with DataGranulesQuery\n",
"\n",
"\n",
"```python\n",
"# An anonymous query to CMR\n",
"Query = DataGranules().keyword('elevation')\n",
"Query = DataGranulesQuery().keyword('elevation')\n",
"# An authenticated query to CMR\n",
"Query = DataGranules(auth).keyword('elevation')\n",
"Query = DataGranulesQuery(auth).keyword('elevation')\n",
"```\n",
"\n",
"\n",
Expand All @@ -109,8 +109,8 @@
"metadata": {},
"outputs": [],
"source": [
"# The first step is to create a DataCollections query\n",
"Query = DataCollections()\n",
"# The first step is to create a DataCollectionsQuery query\n",
"Query = DataCollectionsQuery()\n",
"\n",
"# Use chain methods to customize our query\n",
"Query.short_name(\"ATL06\").version(\"006\")\n",
Expand Down Expand Up @@ -142,7 +142,7 @@
"metadata": {},
"outputs": [],
"source": [
"Query = DataCollections(auth)\n",
"Query = DataCollectionsQuery(auth)\n",
"\n",
"# Use chain methods to customize our query\n",
"Query.short_name(\"ATL06\").version(\"006\")\n",
Expand All @@ -166,7 +166,7 @@
"#### Interpreting the results\n",
"\n",
"The `hits()` method above will tell you the number of query hits, but only for publicly available data sets.\n",
"In this case because cloud hosted ICESat-2 data are not yet publicly available, CMR will return “1” hits, if you filtered DataCollections by provider = NSIDC_CPRD you'll get `0` hits. For now we need an alternative method of seeing how many cloud data sets are available at NSIDC. This is only temporary until cloud-hosted ICESat-2 become publicly available. We can create a collections object (we’re going to want one of these soon anyhow) and print the len() of the collections object to see the true number of hits. \n",
"In this case because cloud hosted ICESat-2 data are not yet publicly available, CMR will return “1” hits, if you filtered DataCollectionsQuery by provider = NSIDC_CPRD you'll get `0` hits. For now we need an alternative method of seeing how many cloud data sets are available at NSIDC. This is only temporary until cloud-hosted ICESat-2 become publicly available. We can create a collections object (we’re going to want one of these soon anyhow) and print the len() of the collections object to see the true number of hits. \n",
"\n",
"> **Note**: Since we cannot rely on `hits()` we need to be aware that `get()` may get us too many metadata records depending on the dataset and how broad our query is.\n"
]
Expand All @@ -179,7 +179,7 @@
"outputs": [],
"source": [
"Query = (\n",
" DataGranules(auth)\n",
" DataGranulesQuery(auth)\n",
" .concept_id(\"C2153572614-NSIDC_CPRD\")\n",
" .bounding_box(-134.7, 58.9, -133.9, 59.2)\n",
" .temporal(\"2020-03-01\", \"2020-03-30\")\n",
Expand Down
10 changes: 5 additions & 5 deletions earthaccess/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
status,
)
from .auth import Auth
from .search import DataCollection, DataCollections, DataGranule, DataGranules
from .services import DataServices
from .search import DataCollection, DataCollectionsQuery, DataGranule, DataGranulesQuery
from .services import DataServicesQuery
from .store import Store
from .system import PROD, UAT
from .virtual import virtualize
Expand All @@ -36,10 +36,10 @@
"Auth",
# search.py
"DataCollection",
"DataCollections",
"DataCollectionsQuery",
"DataGranule",
"DataGranules",
"DataServices",
"DataGranulesQuery",
"DataServicesQuery",
# store.py
"Store",
# api.py
Expand Down
27 changes: 16 additions & 11 deletions earthaccess/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@

import earthaccess
from earthaccess.exceptions import LoginStrategyUnavailable, ServiceOutage
from earthaccess.services import DataServices
from earthaccess.services import DataServicesQuery

from .auth import Auth
from .results import DataCollection, DataGranule
from .search import CollectionQuery, DataCollections, DataGranules, GranuleQuery
from .search import (
CollectionQuery,
DataCollectionsQuery,
DataGranulesQuery,
GranuleQuery,
)
from .store import Store
from .system import PROD, System
from .utils import _validation as validate
Expand Down Expand Up @@ -176,9 +181,9 @@ def search_datasets(count: int = -1, **kwargs: Any) -> list[DataCollection]:
)
return []
if earthaccess.__auth__.authenticated:
query = DataCollections(auth=earthaccess.__auth__).parameters(**kwargs)
query = DataCollectionsQuery(auth=earthaccess.__auth__).parameters(**kwargs)
else:
query = DataCollections().parameters(**kwargs)
query = DataCollectionsQuery().parameters(**kwargs)
datasets_found = query.hits()
logger.info("Datasets found: %s", datasets_found)
if count > 0:
Expand Down Expand Up @@ -270,9 +275,9 @@ def search_data(count: int = -1, **kwargs: Any) -> list[DataGranule]:
```
"""
if earthaccess.__auth__.authenticated:
query = DataGranules(earthaccess.__auth__).parameters(**kwargs)
query = DataGranulesQuery(earthaccess.__auth__).parameters(**kwargs)
else:
query = DataGranules().parameters(**kwargs)
query = DataGranulesQuery().parameters(**kwargs)
granules_found = query.hits()
logger.info("Granules found: %s", granules_found)
if count > 0:
Expand Down Expand Up @@ -301,7 +306,7 @@ def search_services(count: int = -1, **kwargs: Any) -> list[Any]:
services = search_services(provider="POCLOUD", keyword="COG")
```
"""
query = DataServices(auth=earthaccess.__auth__).parameters(**kwargs)
query = DataServicesQuery(auth=earthaccess.__auth__).parameters(**kwargs)
hits = query.hits()
logger.info("Services found: %s", hits)

Expand Down Expand Up @@ -515,9 +520,9 @@ def collection_query() -> CollectionQuery:
a query builder instance for data collections.
"""
if earthaccess.__auth__.authenticated:
query_builder = DataCollections(earthaccess.__auth__)
query_builder = DataCollectionsQuery(earthaccess.__auth__)
else:
query_builder = DataCollections()
query_builder = DataCollectionsQuery()
return query_builder


Expand All @@ -528,9 +533,9 @@ def granule_query() -> GranuleQuery:
a query builder instance for data granules.
"""
if earthaccess.__auth__.authenticated:
query_builder = DataGranules(earthaccess.__auth__)
query_builder = DataGranulesQuery(earthaccess.__auth__)
else:
query_builder = DataGranules()
query_builder = DataGranulesQuery()
return query_builder


Expand Down
4 changes: 2 additions & 2 deletions earthaccess/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import earthaccess

from .formatters import _repr_granule_html
from .services import DataServices
from .services import DataServicesQuery


@cache
Expand Down Expand Up @@ -226,7 +226,7 @@ def services(self) -> dict[Any, list[dict[str, Any]]]:
"""Return list of services available for this collection."""
services = self.get("meta", {}).get("associations", {}).get("services", [])
queries = (
DataServices(auth=earthaccess.__auth__).parameters(concept_id=service)
DataServicesQuery(auth=earthaccess.__auth__).parameters(concept_id=service)
for service in services
)

Expand Down
16 changes: 8 additions & 8 deletions earthaccess/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
type PointLike = tuple[FloatLike, FloatLike]


class DataCollections(CollectionQuery):
class DataCollectionsQuery(CollectionQuery):
"""Query CMR for collection metadata.

???+ Info
The DataCollection class queries against
The DataCollectionsQuery class queries against
https://cmr.earthdata.nasa.gov/search/collections.umm_json,
the response has to be in umm_json to use the result classes.
"""
Expand All @@ -37,7 +37,7 @@ class DataCollections(CollectionQuery):
_format = "umm_json"

def __init__(self, auth: Auth | None = None, *args: Any, **kwargs: Any) -> None:
"""Builds an instance of DataCollections to query the CMR.
"""Builds an instance of DataCollectionsQuery to query the CMR.

Parameters:
auth: An authenticated `Auth` instance. This is an optional parameter
Expand Down Expand Up @@ -223,7 +223,7 @@ def parameters(self, **kwargs: Any) -> Self:

???+ Example
```python
query = DataCollections.parameters(
query = DataCollectionsQuery.parameters(
short_name="AST_L1T",
temporal=("2015-01","2015-02"),
point=(42.5, -101.25)
Expand Down Expand Up @@ -418,7 +418,7 @@ def temporal(
return super().temporal(date_from, date_to, exclude_boundary)


class DataGranules(GranuleQuery):
class DataGranulesQuery(GranuleQuery):
"""A Granule oriented client for NASA CMR.

API: https://cmr.earthdata.nasa.gov/search/site/docs/search/api.html
Expand Down Expand Up @@ -481,7 +481,7 @@ def get(self, limit: int = 2000) -> list[DataGranule]:
limit: The number of results to return.

Returns:
Query results as a (possibly empty) list of `DataGranules` instances.
Query results as a (possibly empty) list of `DataGranule` instances.

Raises:
RuntimeError: The CMR query failed.
Expand All @@ -499,7 +499,7 @@ def parameters(self, **kwargs: Any) -> Self:

???+ Example
```python
query = DataCollections.parameters(
query = DataCollectionsQuery.parameters(
short_name="AST_L1T",
temporal=("2015-01","2015-02"),
point=(42.5, -101.25)
Expand Down Expand Up @@ -945,7 +945,7 @@ def doi(self, doi: str) -> Self:
RuntimeError: The CMR query to get the collection for the DOI fails.
"""
# TODO consider deferring this query until the search is executed
collection = DataCollections().doi(doi).get()
collection = DataCollectionsQuery().doi(doi).get()

# TODO consider raising an exception when there are multiple collections, since
# we can't know which one the user wants, and choosing one is arbitrary.
Expand Down
4 changes: 2 additions & 2 deletions earthaccess/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .utils import _search as search


class DataServices(ServiceQuery):
class DataServicesQuery(ServiceQuery):
"""A Service client for NASA CMR that returns data on collection services.

API: https://cmr.earthdata.nasa.gov/search/site/docs/search/api.html#service
Expand All @@ -17,7 +17,7 @@ class DataServices(ServiceQuery):
_format = "umm_json"

def __init__(self, auth: Auth | None = None, *args: Any, **kwargs: Any) -> None:
"""Build an instance of DataService to query CMR.
"""Build an instance of DataServicesQuery to query CMR.

auth is an optional parameter for queries that need authentication,
e.g. restricted datasets.
Expand Down
4 changes: 2 additions & 2 deletions earthaccess/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from .daac import DAAC_TEST_URLS, find_provider
from .exceptions import DownloadFailure, EulaNotAccepted
from .results import DataGranule
from .search import DataCollections
from .search import DataCollectionsQuery

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -274,7 +274,7 @@ def _derive_daac_provider(self, daac: str) -> str | None:
return find_provider(daac, True) # noqa: FBT003

def _is_cloud_collection(self, concept_id: list[str]) -> bool:
collection = DataCollections(self.auth).concept_id(concept_id).get()
collection = DataCollectionsQuery(self.auth).concept_id(concept_id).get()
return len(collection) > 0 and "s3-links" in collection[0]["meta"]

def _own_s3_credentials(self, links: list[dict[str, Any]]) -> str | None:
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_cloud_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import earthaccess
import pytest
from earthaccess import Auth, DataGranules, Store
from earthaccess import Auth, DataGranulesQuery, Store

from .param import ProviderParam
from .sample import get_sample_granules, top_collections_for_provider
Expand Down Expand Up @@ -77,7 +77,7 @@ def test_earthaccess_can_download_cloud_collection_granules(tmp_path, daac):
logger.info("On-premises collections for %s: %s", provider, len(top_collections))

for concept_id in top_collections:
granule_query = DataGranules().concept_id(concept_id)
granule_query = DataGranulesQuery().concept_id(concept_id)
total_granules = granule_query.hits()
granules = granule_query.get(granules_count)

Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_cloud_open.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import earthaccess
import magic
import pytest
from earthaccess import Auth, DataGranules, Store
from earthaccess import Auth, DataGranulesQuery, Store

from .param import ProviderParam
from .sample import get_sample_granules, top_collections_for_provider
Expand Down Expand Up @@ -71,7 +71,7 @@ def test_earthaccess_can_open_onprem_collection_granules(daac):
logger.info("On-premises collections for %s: %s", provider, len(top_collections))

for concept_id in top_collections:
granule_query = DataGranules().concept_id(concept_id)
granule_query = DataGranulesQuery().concept_id(concept_id)
total_granules = granule_query.hits()
granules = granule_query.get(granules_count)
assert len(granules) > 0, "Could not fetch granules"
Expand Down
Loading
Loading