Skip to content

Commit 7be895d

Browse files
PB-2354 Add validation for CF extension property fields
As for the other extensions (see PB-2355, #658), the CF extension needs to be - enabled on Collection level (`stac_extensions_enabled`) - declared on Item level (`stac_extensions`)
1 parent 23b0b4e commit 7be895d

5 files changed

Lines changed: 66 additions & 22 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Generated by Django 5.2.13 on 2026-08-11 17:03
2+
3+
import django.contrib.postgres.fields
4+
from django.db import migrations
5+
from django.db import models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('stac_api', '0081_remove_item_update_collection_child_trigger_etag_only_and_more'),
12+
]
13+
14+
operations = [
15+
migrations.AlterField(
16+
model_name='collection',
17+
name='stac_extensions_enabled',
18+
field=django.contrib.postgres.fields.ArrayField(
19+
base_field=models.CharField(
20+
choices=[(
21+
'https://stac-extensions.github.io/timestamps/v1.1.0/schema.json',
22+
'Timestamps'
23+
),
24+
(
25+
'https://stac-extensions.github.io/forecast/v0.2.0/schema.json',
26+
'Forecast'
27+
), ('https://stac-extensions.github.io/cf/v1.0.0/schema.json', 'CF')],
28+
max_length=255
29+
),
30+
blank=True,
31+
default=list,
32+
help_text=
33+
'STAC extensions that are enabled for the Items in this Collection. It defines which STAC extensions are allowed to be used by the Items in this Collection. This field is for internal/admin use only, it is not exposed through the STAC API.',
34+
size=None
35+
),
36+
),
37+
migrations.AlterField(
38+
model_name='item',
39+
name='stac_extensions',
40+
field=django.contrib.postgres.fields.ArrayField(
41+
base_field=models.CharField(
42+
choices=[(
43+
'https://stac-extensions.github.io/timestamps/v1.1.0/schema.json',
44+
'Timestamps'
45+
),
46+
(
47+
'https://stac-extensions.github.io/forecast/v0.2.0/schema.json',
48+
'Forecast'
49+
), ('https://stac-extensions.github.io/cf/v1.0.0/schema.json', 'CF')],
50+
max_length=255
51+
),
52+
blank=True,
53+
default=list,
54+
help_text=
55+
"STAC extensions used by this Item. Defined as JSON schema URLs. Must be a subset of the Collection's stac_extensions_enabled field.",
56+
size=None
57+
),
58+
),
59+
]

app/stac_api/serializers/item.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -406,20 +406,6 @@ class Meta:
406406
def get_type(self, obj):
407407
return 'Feature'
408408

409-
def get_stac_extensions(self, obj):
410-
extensions = [
411-
# Extension provides schema for the 'expires' timestamp
412-
"https://stac-extensions.github.io/timestamps/v1.1.0/schema.json"
413-
]
414-
# IMPROVEMENT: This could be improved if there are other extensions coming by
415-
# keeping the information on collection object itself
416-
if obj.collection.name.startswith('ch.meteoschweiz.ogd-forecasting-icon'):
417-
extensions.append("https://stac-extensions.github.io/forecast/v0.2.0/schema.json")
418-
# Add CF extension when CF properties are present
419-
if obj.cf_standard_name is not None or obj.unit is not None:
420-
extensions.append("https://stac-extensions.github.io/cf/v0.2.0/schema.json")
421-
return extensions
422-
423409
def get_stac_version(self, obj):
424410
return get_stac_version(self.context.get('request'))
425411

app/stac_api/validators.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class StacExtension(TextChoices):
3232
'''STAC extensions that can be enabled for a Collection and used by its Items.'''
3333
TIMESTAMPS = 'https://stac-extensions.github.io/timestamps/v1.1.0/schema.json', 'Timestamps'
3434
FORECAST = 'https://stac-extensions.github.io/forecast/v0.2.0/schema.json', 'Forecast'
35+
CF = 'https://stac-extensions.github.io/cf/v1.0.0/schema.json', 'CF'
3536

3637

3738
def validate_stac_extensions_enabled(stac_extensions, collection):
@@ -76,6 +77,8 @@ def validate_item_properties_extensions(properties, stac_extensions):
7677
'forecast:duration': StacExtension.FORECAST,
7778
'forecast:variable': StacExtension.FORECAST,
7879
'forecast:perturbed': StacExtension.FORECAST,
80+
'cf:standard_name': StacExtension.CF,
81+
'unit': StacExtension.CF,
7982
}
8083

8184
errors = {}

app/tests/tests_09/test_items_endpoint.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -678,16 +678,14 @@ def test_item_endpoint_patch(self):
678678
self.assertIn("title", json_data['properties'].keys())
679679

680680
def test_item_endpoint_patch_remove_all_optional_properties(self):
681-
# This test uses the expires/forecast:* properties, which requires the timestamps and
682-
# forecast extensions to be enabled for the collection.
683681
self.collection.model.stac_extensions_enabled = [
684-
StacExtension.TIMESTAMPS, StacExtension.FORECAST
682+
StacExtension.TIMESTAMPS, StacExtension.FORECAST, StacExtension.CF
685683
]
686684
self.collection.model.save()
687685

688686
# First add all properties
689687
data = {
690-
"stac_extensions": [StacExtension.TIMESTAMPS, StacExtension.FORECAST],
688+
"stac_extensions": [StacExtension.TIMESTAMPS, StacExtension.FORECAST, StacExtension.CF],
691689
"properties": {
692690
"title": "patched title",
693691
"expires": "2060-02-12T23:20:50Z",

app/tests/tests_10/test_items_endpoint.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -814,16 +814,14 @@ def test_item_endpoint_patch(self):
814814
self.assertIn("title", json_data['properties'].keys())
815815

816816
def test_item_endpoint_patch_remove_all_optional_properties(self):
817-
# This test uses the expires/forecast:* properties, which requires the timestamps and
818-
# forecast extensions to be enabled for the collection.
819817
self.collection.model.stac_extensions_enabled = [
820-
StacExtension.TIMESTAMPS, StacExtension.FORECAST
818+
StacExtension.TIMESTAMPS, StacExtension.FORECAST, StacExtension.CF
821819
]
822820
self.collection.model.save()
823821

824822
# First add all properties
825823
data = {
826-
"stac_extensions": [StacExtension.TIMESTAMPS, StacExtension.FORECAST],
824+
"stac_extensions": [StacExtension.TIMESTAMPS, StacExtension.FORECAST, StacExtension.CF],
827825
"properties": {
828826
"title": "patched title",
829827
"expires": "2060-02-12T23:20:50Z",

0 commit comments

Comments
 (0)