Skip to content

Commit

Permalink
Merge branch 'main' into format-and-lint-notebooks
Browse files Browse the repository at this point in the history
  • Loading branch information
chuckwondo authored Sep 23, 2024
2 parents ea752f8 + 68e19a2 commit 6a163b8
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 55 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
[**@Sherwin-14**](https://github.com/betolink),
[**@mfisher87**](https://github.com/mfisher87)



### Fixed

- Removed Broken Link "Introduction to NASA earthaccess"
Expand All @@ -41,6 +39,16 @@
- Restore automation for tidying notebooks used in documentation
([#788](https://github.com/nsidc/earthaccess/issues/788))
([**@itcarroll**](https://github.com/itcarroll))
- Remove the base class on `EarthAccessFile` to fix method resolution
([#610](https://github.com/nsidc/earthaccess/issues/610))
([**@itcarroll**](https://github.com/itcarroll))

### Removed

- Remove `binder/` directory, as we no longer need a special [binder](https://mybinder.org)
environment with the top-level `environment.yml` introduced in
[#733](https://github.com/nsidc/earthaccess/issues/733)
([@jhkennedy](https://github.com/jhkennedy))

## [0.10.0] 2024-07-19

Expand Down
24 changes: 0 additions & 24 deletions binder/environment.yml

This file was deleted.

7 changes: 7 additions & 0 deletions docs/user-reference/store/earthaccessfile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Documentation for `EarthAccessFile`

::: earthaccess.store.EarthAccessFile
options:
inherited_members: true
show_root_heading: true
show_source: false
8 changes: 4 additions & 4 deletions earthaccess/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .auth import Auth
from .results import DataCollection, DataGranule
from .search import CollectionQuery, DataCollections, DataGranules, GranuleQuery
from .store import Store
from .store import EarthAccessFile, Store
from .system import PROD, System
from .utils import _validation as validate

Expand Down Expand Up @@ -242,8 +242,8 @@ def download(
def open(
granules: Union[List[str], List[DataGranule]],
provider: Optional[str] = None,
) -> List[AbstractFileSystem]:
"""Returns a list of fsspec file-like objects that can be used to access files
) -> List[EarthAccessFile]:
"""Returns a list of file-like objects that can be used to access files
hosted on S3 or HTTPS by third party libraries like xarray.
Parameters:
Expand All @@ -252,7 +252,7 @@ def open(
provider: e.g. POCLOUD, NSIDC_CPRD, etc.
Returns:
a list of s3fs "file pointers" to s3 files.
A list of "file pointers" to remote (i.e. s3 or https) files.
"""
provider = _normalize_location(provider)
results = earthaccess.__store__.open(granules=granules, provider=provider)
Expand Down
45 changes: 24 additions & 21 deletions earthaccess/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,22 @@
logger = logging.getLogger(__name__)


class EarthAccessFile(fsspec.spec.AbstractBufferedFile):
def __init__(self, f: fsspec.AbstractFileSystem, granule: DataGranule) -> None:
class EarthAccessFile:
"""Handle for a file-like object pointing to an on-prem or Earthdata Cloud granule."""

def __init__(
self, f: fsspec.spec.AbstractBufferedFile, granule: DataGranule
) -> None:
"""EarthAccessFile connects an Earthdata search result with an open file-like object.
No methods exist on the class, which passes all attribute and method calls
directly to the file-like object given during initialization. An instance of
this class can be treated like that file-like object itself.
Parameters:
f: a file-like object
granule: a granule search result
"""
self.f = f
self.granule = granule

Expand All @@ -43,14 +57,14 @@ def __reduce__(self) -> Any:
)

def __repr__(self) -> str:
return str(self.f)
return repr(self.f)


def _open_files(
url_mapping: Mapping[str, Union[DataGranule, None]],
fs: fsspec.AbstractFileSystem,
threads: Optional[int] = 8,
) -> List[fsspec.AbstractFileSystem]:
) -> List[EarthAccessFile]:
def multi_thread_open(data: tuple) -> EarthAccessFile:
urls, granule = data
return EarthAccessFile(fs.open(urls), granule)
Expand Down Expand Up @@ -322,17 +336,17 @@ def open(
self,
granules: Union[List[str], List[DataGranule]],
provider: Optional[str] = None,
) -> List[Any]:
"""Returns a list of fsspec file-like objects that can be used to access files
) -> List[EarthAccessFile]:
"""Returns a list of file-like objects that can be used to access files
hosted on S3 or HTTPS by third party libraries like xarray.
Parameters:
granules: a list of granules(DataGranule) instances or list of URLs,
e.g. s3://some-granule
provider: an option
granules: a list of granule instances **or** list of URLs, e.g. `s3://some-granule`.
If a list of URLs is passed, we need to specify the data provider.
provider: e.g. POCLOUD, NSIDC_CPRD, etc.
Returns:
A list of s3fs "file pointers" to s3 files.
A list of "file pointers" to remote (i.e. s3 or https) files.
"""
if len(granules):
return self._open(granules, provider)
Expand All @@ -344,17 +358,6 @@ def _open(
granules: Union[List[str], List[DataGranule]],
provider: Optional[str] = None,
) -> List[Any]:
"""Returns a list of fsspec file-like objects that can be used to access files
hosted on S3 or HTTPS by third party libraries like xarray.
Parameters:
granules: a list of granules(DataGranule) instances or list of URLs,
e.g. s3://some-granule
provider: an option
Returns:
A list of s3fs "file pointers" to s3 files.
"""
raise NotImplementedError("granules should be a list of DataGranule or URLs")

@_open.register
Expand Down
7 changes: 3 additions & 4 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
name: earthaccess-dev
name: earthaccess
channels:
- conda-forge
dependencies:
# This environment bootstraps pip, the actual dev environment
# is installed and managed with pip
- python=3.10

- python
- pip
- pip:
- --editable .[dev,test,docs]
- --editable ".[dev,test,docs]"
variables:
# Allow pip installs when conda environment is active
PIP_REQUIRE_VENV: 0
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ nav:
- "Granule Queries": "user-reference/granules/granules-query.md"
- "Granule Results": "user-reference/granules/granules.md"
- Store:
- "EarthAccessFile": "user-reference/store/earthaccessfile.md"
- "Store": "user-reference/store/store.md"
- Auth:
- "Auth": "user-reference/auth/auth.md"
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/test_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import responses
import s3fs
from earthaccess import Auth, Store
from earthaccess.store import EarthAccessFile


class TestStoreSessions(unittest.TestCase):
Expand Down Expand Up @@ -126,3 +127,12 @@ def test_store_can_create_s3_fsspec_session(self):
store.get_s3_filesystem()

return None


def test_earthaccess_file_getattr():
fs = fsspec.filesystem("memory")
with fs.open("/foo", "wb") as f:
earthaccess_file = EarthAccessFile(f, granule="foo")
assert f.tell() == earthaccess_file.tell()
# cleanup
fs.store.clear()

0 comments on commit 6a163b8

Please sign in to comment.