Skip to content

Commit 3c1c04f

Browse files
author
Jon Duckworth
authored
Merge pull request #355 from duckontheweb/326-327-extensions
Update EO extension docs
2 parents 543d17f + 6d297b3 commit 3c1c04f

File tree

7 files changed

+350
-114
lines changed

7 files changed

+350
-114
lines changed

docs/api.rst

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ Provider
8888
:members:
8989
:undoc-members:
9090

91+
Summaries
92+
~~~~~~~~~
93+
94+
.. autoclass:: pystac.Summaries
95+
:members:
96+
:undoc-members:
97+
9198
Item Spec
9299
---------
93100

@@ -186,46 +193,74 @@ ExtensionTypeError
186193
Extensions
187194
----------
188195

189-
**TEMPORARILY REMOVED**
190-
.. .. autoclass:: pystac.extensions.Extensions
191-
.. :members:
192-
.. :undoc-members:
193-
194-
ExtensionIndex
195-
~~~~~~~~~~~~~~
196+
Base Classes
197+
------------
196198

197-
**TEMPORARILY REMOVED**
199+
Abstract base classes that should be inherited to implement specific extensions.
198200

199-
.. 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.
201+
SummariesExtension
202+
~~~~~~~~~~~~~~~~~~
200203

201-
.. .. autoclass:: pystac.stac_object.ExtensionIndex
202-
.. :members: __getitem__, __getattr__, enable, implements
204+
.. autoclass:: pystac.extensions.base.SummariesExtension
205+
:members:
203206

207+
PropertiesExtension
208+
~~~~~~~~~~~~~~~~~~~
204209

205-
EO Extension
206-
------------
210+
.. autoclass:: pystac.extensions.base.PropertiesExtension
211+
:members:
212+
:show-inheritance:
207213

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

210-
EOItemExt
211-
~~~~~~~~~
217+
.. autoclass:: pystac.extensions.base.ExtensionManagementMixin
218+
:members:
219+
:show-inheritance:
212220

213-
**TEMPORARILY REMOVED**
221+
Electro-Optical Extension
222+
-------------------------
214223

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

220226
Band
221227
~~~~
222228

223-
**TEMPORARILY REMOVED**
229+
.. autoclass:: pystac.extensions.eo.Band
230+
:members:
231+
:undoc-members:
224232

225-
.. .. autoclass:: pystac.extensions.eo.Band
226-
.. :members:
227-
.. :undoc-members:
233+
EOExtension
234+
~~~~~~~~~~~
228235

236+
.. autoclass:: pystac.extensions.eo.EOExtension
237+
:members:
238+
:undoc-members:
239+
:show-inheritance:
240+
241+
ItemEOExtension
242+
~~~~~~~~~~~~~~~
243+
244+
.. autoclass:: pystac.extensions.eo.ItemEOExtension
245+
:members:
246+
:undoc-members:
247+
:show-inheritance:
248+
249+
AssetEOExtension
250+
~~~~~~~~~~~~~~~~
251+
252+
.. autoclass:: pystac.extensions.eo.AssetEOExtension
253+
:members:
254+
:undoc-members:
255+
:show-inheritance:
256+
257+
SummariesEOExtension
258+
~~~~~~~~~~~~~~~~~~~~
259+
260+
.. autoclass:: pystac.extensions.eo.SummariesEOExtension
261+
:members:
262+
:undoc-members:
263+
:show-inheritance:
229264

230265
Label Extension
231266
---------------
@@ -459,7 +494,7 @@ PySTAC includes a ``pystac.validation`` package for validating STAC objects, inc
459494
from PySTAC objects and directly from JSON.
460495

461496
.. automodule:: pystac.validation
462-
:members: validate, validate_dict, validate_all, set_validator, STACValidationError
497+
:members: validate, validate_dict, validate_all, set_validator
463498

464499
STACValidator
465500
~~~~~~~~~~~~~

docs/concepts.rst

Lines changed: 93 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -309,87 +309,129 @@ The :class:`~pystac.validation.JsonSchemaSTACValidator` takes a :class:`~pystac.
309309
Extensions
310310
==========
311311

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

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

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

326-
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``.
326+
Accessing Extension Functionality
327+
---------------------------------
327328

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

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

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

348350
.. code-block:: python
349351
350-
item.ext.label.label_classes = [label.LabelClasses.create(['class1', 'class2'], name='label')]
352+
eo_ext.bands
353+
eo_ext.cloud_cover
351354
352-
An `apply` method is available in extension wrappers and any objects that they return. This allows
353-
you to pass in property values pertaining to the extension. These will require arguments for properties
354-
required as part of the extension specification and have `None` default values for optional parameters:
355+
See the documentation for each extension implementation for details on the supported
356+
properties and other functionality.
357+
358+
Instances of :class:`~pystac.extensions.base.PropertiesExtension` have a
359+
:attr:`~pystac.extensions.base.PropertiesExtension.properties` attribute that gives
360+
access to the properties of the extended object. *This attribute is a reference to the
361+
properties of the* :class:`~pystac.Item` *or* :class:`~pystac.Asset` *being extended and
362+
can therefore mutate those properties.* For instance:
355363

356364
.. code-block:: python
357365
358-
eo_ext = item.ext.eo
359-
eo_ext.apply(0.5, bands, cloud_cover=None) # Do not have to specify cloud_cover
366+
item = Item.from_file("tests/data-files/eo/eo-landsat-example.json")
367+
print(item.properties["eo:cloud_cover"])
368+
# 78
360369
370+
eo_ext = EOExtension.ext(item)
371+
print(eo_ext.cloud_cover)
372+
# 78
361373
362-
If you attempt to retrieve an extension wrapper for an extension that the object doesn't implement, PySTAC will
363-
throw a `pystac.extensions.ExtensionError`.
374+
eo_ext.cloud_cover = 45
375+
print(item.properties["eo:cloud_cover"])
376+
# 45
364377
365-
Enabling an extension
366-
---------------------
378+
There is also a :attr:`~pystac.extensions.base.PropertiesExtension.additional_read_properties`
379+
attribute that, if present, gives read-only access to properties of any objects that own the
380+
extended object. For instance, an extended :class:`pystac.Asset` instance would have
381+
read access to the properties of the :class:`pystac.Item` that owns it (if there is
382+
one). If a property exists in both additional_read_properties and properties, the value
383+
in additional_read_properties will take precedence.
367384

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

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

373391
.. code-block:: python
374392
375-
item = Item(id='Labels',
376-
geometry=item.geometry,
377-
bbox=item.bbox,
378-
datetime=datetime.utcnow(),
379-
properties={},
380-
stac_extensions=[pystac.Extensions.LABEL])
393+
# Can also omit cloud_cover entirely...
394+
eo_ext.apply(0.5, bands, cloud_cover=None)
395+
381396
382-
or you can call ``ext.enable`` on an Item (which will work for any item, whether you created it or are modifying it):
397+
If you attempt to extend an object that is not supported by an extension, PySTAC will
398+
throw a :class:`pystac.ExtensionTypeError`.
399+
400+
Adding an Extension
401+
-------------------
402+
403+
You can add an extension to a STAC object that does not already implement that extension
404+
using the :meth:`ExtensionManagementMixin.add_to
405+
<pystac.extensions.base.ExtensionManagementMixin.add_to>` method. Any concrete
406+
extension implementations that extend existing STAC objects should inherit from the
407+
:class:`~pystac.extensions.base.ExtensionManagementMixin` class, and will therefore have
408+
this method available. The
409+
:meth:`~pystac.extensions.base.ExtensionManagementMixin.add_to` adds the correct schema
410+
URI to the :attr:`~pystac.STACObject.stac_extensions` list for the object being extended.
383411

384412
.. code-block:: python
385413
386-
item = Item(id='Labels',
387-
geometry=item.geometry,
388-
bbox=item.bbox,
389-
datetime=datetime.utcnow(),
390-
properties={})
414+
# Load a basic item without any extensions
415+
item = Item.from_file("tests/data-files/item/sample-item.json")
416+
print(item.stac_extensions)
417+
# []
418+
419+
# Add the Electro-Optical extension
420+
EOExtension.add_to(item)
421+
print(item.stac_extensions)
422+
# ['https://stac-extensions.github.io/eo/v1.0.0/schema.json']
423+
424+
Extended Summaries
425+
------------------
426+
427+
Extension classes like :class:`~pystac.extensions.eo.EOExtension` may also provide a
428+
``summaries`` static method that can be used to extend the Collection summaries. This
429+
method returns a class inheriting from
430+
:class:`pystac.extensions.base.SummariesExtension` that provides tools for summarizing
431+
the properties defined by that extension. These classes also hold a reference to the
432+
Collection's :class:`pystac.Summaries` instance in the ``summaries`` attribute.
391433

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

394436
Item Asset properties
395437
=====================

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959

6060
extlinks = {
6161
'tutorial': ('https://github.com/azavea/pystac/'
62-
'tree/{}/docs/tutorials/%s'.format(git_branch), 'tutorial')
62+
'tree/{}/docs/tutorials/%s'.format(git_branch), 'tutorial'),
63+
'stac-ext': ('https://github.com/stac-extensions/%s', '%s extension')
6364
}
6465

6566
# Add any paths that contain templates here, relative to this directory.

0 commit comments

Comments
 (0)