Skip to content

Commit

Permalink
Merge remote-tracking branch 'stac-utils/main' into windows-ci-fixes-…
Browse files Browse the repository at this point in the history
…clean

# Conflicts:
#	requirements-dev.txt
#	scripts/test
#	tests/extensions/test_label.py
#	tests/test_catalog.py
#	tests/test_layout.py
#	tests/test_utils.py
#	tests/test_writing.py
  • Loading branch information
duckontheweb committed Jun 1, 2021
2 parents 612a737 + a6ac489 commit 6e0eef7
Show file tree
Hide file tree
Showing 70 changed files with 5,449 additions and 655 deletions.
5 changes: 5 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[report]
fail_under = 89

[run]
source = pystac
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

### Added

- Raster extension support ([#364](https://github.com/stac-utils/pystac/issues/364))
- solar_illumination field in eo extension ([#356](https://github.com/stac-utils/pystac/issues/356))
- Added `Link.canonical` static method for creating links with "canonical" rel type ([#351](https://github.com/stac-utils/pystac/pull/351))
- Added `RelType` enum containing common `rel` values ([#351](https://github.com/stac-utils/pystac/pull/351))

### Changed

### Fixed
Expand All @@ -26,7 +31,7 @@
- Removed type information from docstrings, since it is redundant with function type
annotations ([#342](https://github.com/stac-utils/pystac/pull/342))

## [1.0.0-beta.1]
## [v1.0.0-beta.1]

### Added

Expand Down
108 changes: 82 additions & 26 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ Provider
:members:
:undoc-members:

Summaries
~~~~~~~~~

.. autoclass:: pystac.Summaries
:members:
:undoc-members:

Item Spec
---------

Expand Down Expand Up @@ -134,6 +141,13 @@ MediaType
:members:
:undoc-members:

RelType
~~~~~~~

.. autoclass:: pystac.RelType
:members:
:undoc-members:

IO
--

Expand Down Expand Up @@ -186,46 +200,74 @@ ExtensionTypeError
Extensions
----------

**TEMPORARILY REMOVED**
.. .. autoclass:: pystac.extensions.Extensions
.. :members:
.. :undoc-members:
ExtensionIndex
~~~~~~~~~~~~~~
Base Classes
------------

**TEMPORARILY REMOVED**
Abstract base classes that should be inherited to implement specific extensions.

.. An ExtensionIndex is accessed through the :attr:`STACObject.ext <pystac.STACObject.ext>` property and is the primary way to access information and functionality around STAC extensions.
SummariesExtension
~~~~~~~~~~~~~~~~~~

.. .. autoclass:: pystac.stac_object.ExtensionIndex
.. :members: __getitem__, __getattr__, enable, implements
.. autoclass:: pystac.extensions.base.SummariesExtension
:members:

PropertiesExtension
~~~~~~~~~~~~~~~~~~~

EO Extension
------------
.. autoclass:: pystac.extensions.base.PropertiesExtension
:members:
:show-inheritance:

These classes are representations of the `EO Extension Spec <https://github.com/radiantearth/stac-spec/tree/v1.0.0-beta.2/extensions/eo>`_.
ExtensionManagementMixin
~~~~~~~~~~~~~~~~~~~~~~~~

EOItemExt
~~~~~~~~~
.. autoclass:: pystac.extensions.base.ExtensionManagementMixin
:members:
:show-inheritance:

**TEMPORARILY REMOVED**
Electro-Optical Extension
-------------------------

.. .. autoclass:: pystac.extensions.eo.EOItemExt
.. :members:
.. :undoc-members:
.. :show-inheritance:
These classes are representations of the `EO Extension Spec <https://github.com/radiantearth/stac-spec/tree/v1.0.0-beta.2/extensions/eo>`_.

Band
~~~~

**TEMPORARILY REMOVED**
.. autoclass:: pystac.extensions.eo.Band
:members:
:undoc-members:

.. .. autoclass:: pystac.extensions.eo.Band
.. :members:
.. :undoc-members:
EOExtension
~~~~~~~~~~~

.. autoclass:: pystac.extensions.eo.EOExtension
:members:
:undoc-members:
:show-inheritance:

ItemEOExtension
~~~~~~~~~~~~~~~

.. autoclass:: pystac.extensions.eo.ItemEOExtension
:members:
:undoc-members:
:show-inheritance:

AssetEOExtension
~~~~~~~~~~~~~~~~

.. autoclass:: pystac.extensions.eo.AssetEOExtension
:members:
:undoc-members:
:show-inheritance:

SummariesEOExtension
~~~~~~~~~~~~~~~~~~~~

.. autoclass:: pystac.extensions.eo.SummariesEOExtension
:members:
:undoc-members:
:show-inheritance:

Label Extension
---------------
Expand All @@ -242,6 +284,13 @@ LabelItemExt
.. :undoc-members:
.. :show-inheritance:
LabelRelType
~~~~~~~~~~~~

.. autoclass:: pystac.extensions.label.LabelRelType
:members:
:show-inheritance:

LabelType
~~~~~~~~~

Expand Down Expand Up @@ -376,6 +425,13 @@ Version Extension

Implements the `Version Extension <https://github.com/radiantearth/stac-spec/tree/v1.0.0-beta.2/extensions/version>`_.

VersionRelType
~~~~~~~~~~~~~~

.. autoclass:: pystac.extensions.version.VersionRelType
:members:
:show-inheritance:

VersionCollectionExt
~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -459,7 +515,7 @@ PySTAC includes a ``pystac.validation`` package for validating STAC objects, inc
from PySTAC objects and directly from JSON.

.. automodule:: pystac.validation
:members: validate, validate_dict, validate_all, set_validator, STACValidationError
:members: validate, validate_dict, validate_all, set_validator

STACValidator
~~~~~~~~~~~~~
Expand Down
144 changes: 93 additions & 51 deletions docs/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -309,87 +309,129 @@ The :class:`~pystac.validation.JsonSchemaSTACValidator` takes a :class:`~pystac.
Extensions
==========

Accessing Extension functionality
---------------------------------

All STAC objects are accessed through ``Catalog``, ``Collection`` and ``Item``, and all extension functionality
is accessed through the ``ext`` property on those objects. For instance, to access the band information
from the ``eo`` extension for an item that implements the extension, you use:
From the documentation on `STAC Spec Extensions
<https://github.com/radiantearth/stac-spec/tree/master/extensions>`__:

.. code-block:: python
Extensions to the core STAC specification provide additional JSON fields that can be
used to better describe the data. Most tend to be about describing a particular
domain or type of data, but some imply functionality.

# All of the below are equivalent:
item.ext['eo'].bands
item.ext[pystac.Extensions.EO].bands
item.ext.eo.bands
This library makes an effort to support all extensions that are part of the
`stac-extensions GitHub org
<https://stac-extensions.github.io/#extensions-in-stac-extensions-organization>`__, and
we are committed to supporting all STAC Extensions at the "Candidate" maturity level or
above (see the `Extension Maturity
<https://stac-extensions.github.io/#extension-maturity>`__ documentation for details).

Notice the ``eo`` property on ``ext`` - this utilizes the `__getattr__ <https://docs.python.org/3/reference/datamodel.html#object.__getattr__>`_ method to delegate the property name to the ``__getitem__`` method, so we can access any registered extension as if it were a property on ``ext``.
Accessing Extension Functionality
---------------------------------

Extensions wrap the objects they extend. Extensions hold
no values of their own, but instead use Python `properties <https://docs.python.org/3/library/functions.html#property>`_
to directly modify the values of the objects they wrap.
Extension functionality is encapsulated in classes that are specific to the STAC
Extension (e.g. Electro-Optical, Projection, etc.) and STAC Object
(:class:`~pystac.Collection`, :class:`pystac.Item`, or :class:`pystac.Asset`). All
classes that extend these objects inherit from
:class:`pystac.extensions.base.PropertiesExtension`, and you can use the
``ext`` method on these classes to extend an object.

Any object that is returned by extension methods therefore also wrap components of the STAC objects.
For instance, the ``LabelClasses`` holds a reference to the original ``Item``'s ``label:classes`` property, so that
modifying the ``LabelClasses``
properties through the setters will modify the item properties directly. For example:
For instance, to extend an item with the :stac-ext:`Electro-Optical Extension <eo>`
you would use :meth:`EOExtension.ext <pystac.extensions.eo.EOExtension.ext>` as
follows:

.. code-block:: python
from pystac.extensions import label
import pystac
from pystac.extensions.eo import EOExtension
label_classes = item.ext.label.label_classes
label_classes[0].classes.append("other_class")
assert "other_class" in item.properties['label:classes'][0]['classes']
item = Item(...) # See docs for creating an Item
eo_ext = EOExtension.ext(item)
Because these objects wrap the object's dictionary, the __init__ methods need to take the
``dict`` they wrap. Therefore to create a new object, use the class's `.create` method, for example:
This extended instance now gives you access to the properties defined in that extension:

.. code-block:: python
item.ext.label.label_classes = [label.LabelClasses.create(['class1', 'class2'], name='label')]
eo_ext.bands
eo_ext.cloud_cover
An `apply` method is available in extension wrappers and any objects that they return. This allows
you to pass in property values pertaining to the extension. These will require arguments for properties
required as part of the extension specification and have `None` default values for optional parameters:
See the documentation for each extension implementation for details on the supported
properties and other functionality.

Instances of :class:`~pystac.extensions.base.PropertiesExtension` have a
:attr:`~pystac.extensions.base.PropertiesExtension.properties` attribute that gives
access to the properties of the extended object. *This attribute is a reference to the
properties of the* :class:`~pystac.Item` *or* :class:`~pystac.Asset` *being extended and
can therefore mutate those properties.* For instance:

.. code-block:: python
eo_ext = item.ext.eo
eo_ext.apply(0.5, bands, cloud_cover=None) # Do not have to specify cloud_cover
item = Item.from_file("tests/data-files/eo/eo-landsat-example.json")
print(item.properties["eo:cloud_cover"])
# 78
eo_ext = EOExtension.ext(item)
print(eo_ext.cloud_cover)
# 78
If you attempt to retrieve an extension wrapper for an extension that the object doesn't implement, PySTAC will
throw a `pystac.extensions.ExtensionError`.
eo_ext.cloud_cover = 45
print(item.properties["eo:cloud_cover"])
# 45
Enabling an extension
---------------------
There is also a :attr:`~pystac.extensions.base.PropertiesExtension.additional_read_properties`
attribute that, if present, gives read-only access to properties of any objects that own the
extended object. For instance, an extended :class:`pystac.Asset` instance would have
read access to the properties of the :class:`pystac.Item` that owns it (if there is
one). If a property exists in both additional_read_properties and properties, the value
in additional_read_properties will take precedence.

You'll need to enable an extension on an object before using it. For example, if you are creating an Item and want to
apply the label extension, you can do so in two ways.

You can add the extension in the list of extensions when you create the Item:
An ``apply`` method is available on extended objects. This allows you to pass in
property values pertaining to the extension. Properties that are required by the
extension will be required arguments to the ``apply`` method. Optional properties will
have a default value of ``None``:

.. code-block:: python
item = Item(id='Labels',
geometry=item.geometry,
bbox=item.bbox,
datetime=datetime.utcnow(),
properties={},
stac_extensions=[pystac.Extensions.LABEL])
# Can also omit cloud_cover entirely...
eo_ext.apply(0.5, bands, cloud_cover=None)
or you can call ``ext.enable`` on an Item (which will work for any item, whether you created it or are modifying it):
If you attempt to extend an object that is not supported by an extension, PySTAC will
throw a :class:`pystac.ExtensionTypeError`.

Adding an Extension
-------------------

You can add an extension to a STAC object that does not already implement that extension
using the :meth:`ExtensionManagementMixin.add_to
<pystac.extensions.base.ExtensionManagementMixin.add_to>` method. Any concrete
extension implementations that extend existing STAC objects should inherit from the
:class:`~pystac.extensions.base.ExtensionManagementMixin` class, and will therefore have
this method available. The
:meth:`~pystac.extensions.base.ExtensionManagementMixin.add_to` adds the correct schema
URI to the :attr:`~pystac.STACObject.stac_extensions` list for the object being extended.

.. code-block:: python
item = Item(id='Labels',
geometry=item.geometry,
bbox=item.bbox,
datetime=datetime.utcnow(),
properties={})
# Load a basic item without any extensions
item = Item.from_file("tests/data-files/item/sample-item.json")
print(item.stac_extensions)
# []
# Add the Electro-Optical extension
EOExtension.add_to(item)
print(item.stac_extensions)
# ['https://stac-extensions.github.io/eo/v1.0.0/schema.json']
Extended Summaries
------------------

Extension classes like :class:`~pystac.extensions.eo.EOExtension` may also provide a
``summaries`` static method that can be used to extend the Collection summaries. This
method returns a class inheriting from
:class:`pystac.extensions.base.SummariesExtension` that provides tools for summarizing
the properties defined by that extension. These classes also hold a reference to the
Collection's :class:`pystac.Summaries` instance in the ``summaries`` attribute.

item.ext.enable(pystac.Extensions.LABEL)
See :class:`pystac.extensions.eo.SummariesEOExtension` for an example implementation.

Item Asset properties
=====================
Expand Down
Loading

0 comments on commit 6e0eef7

Please sign in to comment.