Skip to content

Commit

Permalink
Merge pull request #20 from asfadmin/feature-core-search
Browse files Browse the repository at this point in the history
Core search features
  • Loading branch information
glshort authored Apr 14, 2021
2 parents e15dfeb + 24ffe90 commit 2891815
Show file tree
Hide file tree
Showing 32 changed files with 329 additions and 187 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@

## [0.3.0](https://github.com/asfadmin/Discovery-asf_search/compare/v0.2.4...v0.3.0)

### Added
- Layed out framework for INSTRUMENT constants (needs to be populated)
- Support for baseline stacking of pre-calculated datasets
- Download support for single products or entire search result sets, token-based auth only
- ASFSearchResults and ASFProduct classes
- Lower-level ASFError exception class
- ASFDownloadError exception class
- ASFBaselineError exception class
- Better path/frame/platform/product example

### Changed
- No longer uses range type for parameters that accept lists of values and/or ranges. Now expects a 2-value tuple.
- Removed DATASET constants (not searchable, use platform+instrument to identify a dataset)
- Updated hello_world.py baseline example
- Removed output options across the board, geojson only until we no longer rely on SearchAPI calls
- insarStackID now a search option (needed for baseline stacking of pre-calculated datasets)
- Flatter structure for constants
- baseline functionality moved into search group (file restructuring)

### Fixed
- Corrected handling of version number in user agent string
- unused import cleanup
- better type hinting on centroid() function

## [0.2.4](https://github.com/asfadmin/Discovery-asf_search/compare/v0.0.0...v0.2.4)

Expand Down
1 change: 0 additions & 1 deletion asf_search/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from .constants import *
from .health import *
from .search import *
from .baseline import *

try:
__version__ = version(__name__)
Expand Down
1 change: 0 additions & 1 deletion asf_search/baseline/__init__.py

This file was deleted.

94 changes: 0 additions & 94 deletions asf_search/baseline/baseline.py

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions asf_search/constants/BEAMMODE/__init__.py

This file was deleted.

12 changes: 0 additions & 12 deletions asf_search/constants/DATASET/DATASET.py

This file was deleted.

3 changes: 0 additions & 3 deletions asf_search/constants/DATASET/__init__.py

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions asf_search/constants/FLIGHT_DIRECTION/__init__.py

This file was deleted.

Empty file.
File renamed without changes.
3 changes: 0 additions & 3 deletions asf_search/constants/INTERNAL/__init__.py

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions asf_search/constants/PLATFORM/__init__.py

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions asf_search/constants/POLARIZATION/__init__.py

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions asf_search/constants/PRODUCT_TYPE/__init__.py

This file was deleted.

14 changes: 7 additions & 7 deletions asf_search/constants/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""Various constants to be used in search and related functions, provided as a convenience to help ensure sensible values."""

from .DATASET import DATASET
from .PLATFORM import PLATFORM
from .POLARIZATION import POLARIZATION
from .BEAMMODE import BEAMMODE
from .FLIGHT_DIRECTION import FLIGHT_DIRECTION
from .PRODUCT_TYPE import PRODUCT_TYPE
from .INTERNAL import INTERNAL
from .BEAMMODE import *
from .FLIGHT_DIRECTION import *
from .INSTRUMENT import *
from .PLATFORM import *
from .POLARIZATION import *
from .PRODUCT_TYPE import *
from .INTERNAL import *

#TODO: add INSTRUMENT constants
1 change: 1 addition & 0 deletions asf_search/download/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .download import download_url
45 changes: 45 additions & 0 deletions asf_search/download/download.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import os.path
import urllib.parse
import requests
from importlib.metadata import PackageNotFoundError, version
from ..exceptions import ASFDownloadError


def download_url(url: str, dir: str, filename: str = None, token: str = None) -> None:
"""
Downloads a product from the specified URL to the specified location and (optional) filename.
:param url: URL from which to download
:param dir: Directory in which to save the product
:param filename: Optional filename to be used, extracted from the URL by default
:param token: EDL Auth Token for authenticating downloads, see https://urs.earthdata.nasa.gov/user_tokens
:return:
"""
if filename is None:
filename = os.path.split(urllib.parse.urlparse(url).path)[1]

if not os.path.isdir(dir):
raise ASFDownloadError(f'Error downloading {url}: directory not found: {dir}')

if os.path.isfile(os.path.join(dir, filename)):
raise ASFDownloadError(f'File already exists: {os.path.join(dir, filename)}')

try:
pkg_version = version(__name__)
except PackageNotFoundError:
pkg_version = '0.0.0'
headers = {'User-Agent': f'{__name__}.{pkg_version}'}
if token is not None:
headers['Authorization'] = f'Bearer {token}'

response = requests.get(url, stream=True, allow_redirects=False)
while 300 <= response.status_code <= 399:
new_url = response.headers['location']
if 'aws.amazon.com' in urllib.parse.urlparse(new_url).netloc:
response = requests.get(new_url, stream=True, allow_redirects=False) # S3 detests auth headers
else:
response = requests.get(new_url, stream=True, headers=headers, allow_redirects=False)
response.raise_for_status()
with open(os.path.join(dir, filename), 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
17 changes: 13 additions & 4 deletions asf_search/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
class ASFSearchError(Exception):
"""Base Exception for asf_search"""
class ASFError(Exception):
"""Base ASF Exception, not intended for direct use"""

class ASFSearchError(ASFError):
"""Base search-related Exception"""

class ASFSearch4xxError(ASFSearchError):
"""Raise when SearchAPI returns a 4xx error"""

class ASFSearch5xxError(ASFSearchError):
"""Raise when SearchAPI returns a 5xx error"""

class ServerError(ASFSearchError):
"""Raise when SearchAPI returns an unknown error"""
class ASFServerError(ASFSearchError):
"""Raise when SearchAPI returns an unknown error"""

class ASFBaselineError(ASFSearchError):
"""Raise when baseline related errors occur"""

class ASFDownloadError(ASFError):
"""Base download-related Exception"""
3 changes: 3 additions & 0 deletions asf_search/search/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
from .granule_search import granule_search
from .product_search import product_search
from .geo_search import geo_search
from .baseline_search import stack_from_id
from .product import ASFProduct
from .results import ASFSearchResults
Loading

0 comments on commit 2891815

Please sign in to comment.