Skip to content

Commit

Permalink
Merge pull request #212 from descarteslabs/export
Browse files Browse the repository at this point in the history
v0.8.0 Candidate
  • Loading branch information
jpoehnelt authored Mar 30, 2018
2 parents 274897f + bfceb0f commit 56566a7
Show file tree
Hide file tree
Showing 26 changed files with 482 additions and 2,171 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ before_install:
- pip install --upgrade pip setuptools
install:
- pip install --upgrade -r requirements.txt
- pip install .
- pip install flake8 coverage nose mock
script:
- if [[ $TRAVIS_PYTHON_VERSION == "3.5" ]]; then nosetests --with-coverage --cover-package=descarteslabs
--with-doctest --doctest-options=+ELLIPSIS,+NORMALIZE_WHITESPACE && flake8; fi
- if [[ $TRAVIS_PYTHON_VERSION != "3.5" ]]; then nosetests --with-coverage --cover-package=descarteslabs;
fi
- pip install .
notifications:
slack:
on_success: change
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,21 @@ $ export CLIENT_SECRET=...

Documentation
-------------
The documentation for the latest release can be found on [readthedocs](http://descartes-labs-python.readthedocs.io/)
The documentation for the latest release can be found at [https://docs.descarteslabs.com](https://docs.descarteslabs.com)

Changelog
=========

## [Unreleased]
## [0.8.0] - 2018-02-08
## [0.8.0] - 2018-03-29
### Changed
- Removed deprecated searching by const_id
- Removed deprecated searching by `const_id`
- Removed deprecated raster band methods
- Deprecated `sat_id` parameter for metadata searches
- Changed documentation from readthedocs to https://docs.descarteslabs.com

### Added
- Dot notation access to dictionaries returned by services

## [0.7.0] - 2018-01-24
### Changed
Expand Down
13 changes: 1 addition & 12 deletions descarteslabs/client/auth/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from six.moves import input

from descarteslabs.client.auth.auth import Auth, base64url_decode, makedirs_if_not_exists, DEFAULT_TOKEN_INFO_PATH
from descarteslabs.client.services.metadata import Metadata
from descarteslabs.client.version import __version__


Expand Down Expand Up @@ -53,20 +52,10 @@ def auth_handler(args):

# Get a fresh Auth token
auth = Auth()
keys = Metadata(auth=auth).keys()

name = auth.payload['name']
groups = ', '.join(auth.payload['groups'])

if len(keys):

print('Welcome, %s!' % name)

else:

print('Welcome, %s! Your %s role(s) do not permit access to any imagery at this time.' % (name, groups))
print(
'Contact [email protected] if you believe you received this message in error or have any questions.') # NOQA
print('Welcome, %s!' % name)

if args.command == 'token':
print(auth.token)
Expand Down
7 changes: 7 additions & 0 deletions descarteslabs/client/auth/readme.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. `_descarteslabs_client_auth`
Authentication
--------------
.. automodule:: descarteslabs.client.auth
:members:
:undoc-members:
5 changes: 5 additions & 0 deletions descarteslabs/client/readme.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Exceptions
----------
.. automodule:: descarteslabs.client.exceptions
:members:
:undoc-members:
11 changes: 2 additions & 9 deletions descarteslabs/client/services/metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,8 @@
# limitations under the License.

from .metadata import Metadata
from .metadata_filtering import Properties
from .metadata_filtering import GLOBAL_PROPERTIES

properties = Properties("absolute_orbit", "acquired", "archived", "area", "azimuth_angle",
"bright_fraction", "cirrus_fraction", "cloud_fraction", "cloud_fraction_0",
"cloud_fraction_1", "descartes_version", "earth_sun_distance",
"fill_fraction", "geolocation_accuracy", "opaque_fraction", "product", "processed",
"published", "relative_orbit", "roll_angle", "sat_id", "solar_azimuth_angle",
"solar_azimuth_angle_0", "solar_elevation_angle", "solar_elevation_angle_0",
"sw_version", "terrain_correction", "tile_id", "view_angle", "view_angle_0",
"view_angle_1")
properties = GLOBAL_PROPERTIES

__all__ = ["Metadata", "properties"]
102 changes: 60 additions & 42 deletions descarteslabs/client/services/metadata/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,27 @@
from descarteslabs.client.services.places import Places
from descarteslabs.client.auth import Auth
from descarteslabs.client.services.raster import Raster
from descarteslabs.client.services.metadata.metadata_filtering import AndExpression
from descarteslabs.client.services.metadata.metadata_filtering import \
AndExpression, GLOBAL_PROPERTIES
from descarteslabs.common.dotdict import DotDict, DotList


OFFSET_DEPRECATION_MESSAGE = (
"Keyword arg `offset` has been deprecated and will be removed in "
"future versions of the library. "
)

SAT_ID_DEPRECATION_MESSAGE = (
"Keyword arg `sat_id` has been deprecated and will be removed in "
"future versions of the library. "
)

SOURCES_DEPRECATION_MESSAGE = (
"Metadata.sources() has been deprecated and will be removed in "
"future versions of the library. Please use "
"Metadata.available_products() or Metadata.products() instead. "
)


class Metadata(Service):
"""
Expand All @@ -41,32 +54,29 @@ class Metadata(Service):

TIMEOUT = (9.5, 120)

def __init__(self, url=None, token=None, auth=Auth()):
properties = GLOBAL_PROPERTIES

def __init__(self, url=None, auth=None):
"""The parent Service class implements authentication and exponential
backoff/retry. Override the url parameter to use a different instance
of the backing service.
"""
if auth is None:
auth = Auth()

simplefilter('always', DeprecationWarning)
if url is None:
url = os.environ.get("DESCARTESLABS_METADATA_URL",
"https://platform.descarteslabs.com/metadata/v1")

Service.__init__(self, url, token, auth)
super(Metadata, self).__init__(url, auth)
self._raster = Raster(auth=self.auth)

def sources(self):
"""Get a list of image sources.
warn(SOURCES_DEPRECATION_MESSAGE, DeprecationWarning)

Example::
>>> from descarteslabs.client.services import Metadata
>>> from pprint import pprint
>>> sources = Metadata().sources()
>>> pprint(sources)
[{'product': 'landsat:LC08:PRE:TOAR', 'sat_id': 'LANDSAT_8'}]
"""
r = self.session.get('/sources')
return r.json()
return DotList(r.json())

def bands(
self,
Expand Down Expand Up @@ -101,7 +111,7 @@ def bands(
})

r = self.session.post('/bands/search', json=kwargs)
return r.json()
return DotList(r.json())

def derived_bands(self, bands=None, require_bands=None, limit=None, offset=None, **kwargs):
"""Search for predefined derived bands that you have access to.
Expand All @@ -125,7 +135,7 @@ def derived_bands(self, bands=None, require_bands=None, limit=None, offset=None,
})

r = self.session.post('/bands/derived/search', json=kwargs)
return r.json()
return DotList(r.json())

def get_bands_by_key(self, key):
"""
Expand All @@ -137,7 +147,7 @@ def get_bands_by_key(self, key):
"""
r = self.session.get('/bands/key/%s' % key)

return r.json()
return DotDict(r.json())

def products(self, bands=None, limit=None, offset=None, owner=None, text=None, **kwargs):
"""Search products that are available on the platform.
Expand All @@ -161,22 +171,21 @@ def products(self, bands=None, limit=None, offset=None, owner=None, text=None, *

r = self.session.post('/products/search', json=kwargs)

return r.json()
return DotList(r.json())

def available_products(self):
"""Get the list of product identifiers you have access to.
Example::
>>> from descarteslabs.client.services import Metadata
>>> from pprint import pprint
>>> products = Metadata().available_products()
>>> pprint(products)
>>> products
['landsat:LC08:PRE:TOAR']
"""
r = self.session.get('/products')

return r.json()
return DotList(r.json())

def summary(self, products=None, sat_id=None, date='acquired', part=None,
place=None, geom=None, start_time=None, end_time=None, cloud_fraction=None,
Expand All @@ -185,7 +194,7 @@ def summary(self, products=None, sat_id=None, date='acquired', part=None,
"""Get a summary of the results for the specified spatio-temporal query.
:param list(str) products: Product identifier(s).
:param list(str) sat_id: Satellite identifier(s).
:param list(str) sat_id: Satellite identifier(s). *Deprecated*
:param str date: The date field to use for search (e.g. `acquired`).
:param str part: Part of the date to aggregate over (e.g. `day`).
:param str place: A slug identifier to be used as a region of interest.
Expand All @@ -202,19 +211,24 @@ def summary(self, products=None, sat_id=None, date='acquired', part=None,
Example usage::
>>> from descarteslabs.client.services import Metadata
>>> from pprint import pprint
>>> pprint(Metadata().summary(place='north-america_united-states_iowa', \
>>> Metadata().summary(place='north-america_united-states_iowa', \
products=['landsat:LC08:PRE:TOAR'], start_time='2016-07-06', \
end_time='2016-07-07', part='hour', pixels=True))
{'bytes': 93298309,
'count': 1,
'items': [{'bytes': 93298309,
'count': 1,
'date': '2016-07-06T16:00:00',
'pixels': 250508160,
'timestamp': 1467820800}],
'pixels': 250508160,
'products': ['landsat:LC08:PRE:TOAR']}
end_time='2016-07-07', part='hour', pixels=True)
{
'bytes': 93298309,
'count': 1,
'items': [
{
'bytes': 93298309,
'count': 1,
'date': '2016-07-06T16:00:00',
'pixels': 250508160,
'timestamp': 1467820800
}
],
'pixels': 250508160,
'products': ['landsat:LC08:PRE:TOAR']
}
"""
if place:
places = Places()
Expand All @@ -234,6 +248,8 @@ def summary(self, products=None, sat_id=None, date='acquired', part=None,
kwargs = {}

if sat_id:
warn(SAT_ID_DEPRECATION_MESSAGE, DeprecationWarning)

if isinstance(sat_id, string_types):
sat_id = [sat_id]

Expand Down Expand Up @@ -278,7 +294,7 @@ def summary(self, products=None, sat_id=None, date='acquired', part=None,
kwargs['pixels'] = pixels

r = self.session.post('/summary', json=kwargs)
return r.json()
return DotDict(r.json())

def search(self, products=None, sat_id=None, date='acquired', place=None,
geom=None, start_time=None, end_time=None, cloud_fraction=None,
Expand Down Expand Up @@ -341,6 +357,8 @@ def search(self, products=None, sat_id=None, date='acquired', place=None,
kwargs['offset'] = offset

if sat_id:
warn(SAT_ID_DEPRECATION_MESSAGE, DeprecationWarning)

if isinstance(sat_id, string_types):
sat_id = [sat_id]

Expand Down Expand Up @@ -398,7 +416,7 @@ def search(self, products=None, sat_id=None, date='acquired', place=None,
fc['properties'] = {
'continuation_token': r.headers['x-continuation-token']}

return fc
return DotDict(fc)

def ids(self, products=None, sat_id=None, date='acquired', place=None,
geom=None, start_time=None, end_time=None, cloud_fraction=None,
Expand Down Expand Up @@ -448,7 +466,7 @@ def ids(self, products=None, sat_id=None, date='acquired', place=None,
q=q, limit=limit, offset=offset, fields=[], dltile=dltile,
sort_field=sort_field, sort_order=sort_order, randomize=randomize)

return [feature['id'] for feature in result['features']]
return DotList(feature['id'] for feature in result['features'])

def keys(self, products=None, sat_id=None, date='acquired', place=None,
geom=None, start_time=None, end_time=None, cloud_fraction=None,
Expand Down Expand Up @@ -499,7 +517,7 @@ def keys(self, products=None, sat_id=None, date='acquired', place=None,
dltile=dltile, sort_field=sort_field,
sort_order=sort_order, randomize=randomize)

return [feature['key'] for feature in result['features']]
return DotList(feature['key'] for feature in result['features'])

def features(self, products=None, sat_id=None, date='acquired', place=None,
geom=None, start_time=None, end_time=None, cloud_fraction=None,
Expand Down Expand Up @@ -569,7 +587,7 @@ def get(self, key):
'tile_id']
"""
r = self.session.get('/get/%s' % key)
return r.json()
return DotDict(r.json())

def get_by_ids(self, ids):
"""Get metadata for multiple images by id. The response contains found images in the
Expand All @@ -579,7 +597,7 @@ def get_by_ids(self, ids):
:return: List of image metadata.
"""
r = self.session.post('/batch/images', json={'ids': ids})
return r.json()
return DotList(r.json())

def get_product(self, product_id):
"""Get information about a single product.
Expand All @@ -588,7 +606,7 @@ def get_product(self, product_id):
"""
r = self.session.get('/products/%s' % product_id)
return r.json()
return DotDict(r.json())

def get_band(self, band_id):
"""Get information about a single product.
Expand All @@ -597,7 +615,7 @@ def get_band(self, band_id):
"""
r = self.session.get('/bands/%s' % band_id)
return r.json()
return DotDict(r.json())

def get_derived_band(self, derived_band_id):
"""Get information about a single product.
Expand All @@ -606,4 +624,4 @@ def get_derived_band(self, derived_band_id):
"""
r = self.session.get('/bands/derived/%s' % derived_band_id)
return r.json()
return DotDict(r.json())
12 changes: 12 additions & 0 deletions descarteslabs/client/services/metadata/metadata_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,15 @@ def __getattr__(self, attr):

raise AttributeError(
"'Properties' object has no attribute '{}'".format(attr))


GLOBAL_PROPERTIES = Properties(
"absolute_orbit", "acquired", "archived", "area", "azimuth_angle",
"bright_fraction", "cirrus_fraction", "cloud_fraction", "cloud_fraction_0",
"cloud_fraction_1", "descartes_version", "earth_sun_distance",
"fill_fraction", "geolocation_accuracy", "opaque_fraction", "product", "processed",
"published", "relative_orbit", "roll_angle", "sat_id", "solar_azimuth_angle",
"solar_azimuth_angle_0", "solar_elevation_angle", "solar_elevation_angle_0",
"sw_version", "terrain_correction", "tile_id", "view_angle", "view_angle_0",
"view_angle_1"
)
Loading

0 comments on commit 56566a7

Please sign in to comment.