Skip to content

Commit e611092

Browse files
remicresgadomski
andauthored
fix #1483 (#1484)
* fix #1483 * add a test for #1483 * fix: rewrite cassette * fix: formatting --------- Co-authored-by: Pete Gadomski <[email protected]>
1 parent 97f87cb commit e611092

File tree

3 files changed

+176
-2
lines changed

3 files changed

+176
-2
lines changed

pystac/extensions/classification.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,10 @@ def apply(
525525
or bitfields is None
526526
and classes is not None
527527
), "Must set exactly one of `classes` or `bitfields`"
528-
self.classes = classes
529-
self.bitfields = bitfields
528+
if classes:
529+
self.classes = classes
530+
if bitfields:
531+
self.bitfields = bitfields
530532

531533
@property
532534
def classes(self) -> list[Classification] | None:
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Connection:
6+
- close
7+
Host:
8+
- stac-extensions.github.io
9+
User-Agent:
10+
- Python-urllib/3.12
11+
method: GET
12+
uri: https://stac-extensions.github.io/classification/v2.0.0/schema.json
13+
response:
14+
body:
15+
string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\":
16+
\"https://stac-extensions.github.io/classification/v2.0.0/schema.json#\",\n
17+
\ \"title\": \"Classification Extension\",\n \"description\": \"STAC Classification
18+
Extension for STAC Items and STAC Collections.\",\n \"type\": \"object\",\n
19+
\ \"required\": [\"stac_extensions\"],\n \"properties\": {\n \"stac_extensions\":
20+
{\n \"type\": \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/classification/v2.0.0/schema.json\"\n
21+
\ }\n }\n },\n \"oneOf\": [\n {\n \"$comment\": \"This is
22+
the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\":
23+
[\"type\", \"properties\", \"assets\"],\n \"properties\": {\n \"type\":
24+
{\n \"const\": \"Feature\"\n },\n \"properties\": {\n
25+
\ \"$comment\": \"This validates the fields in Item Properties, but
26+
does not require them.\",\n \"allOf\": [\n {\n \"$ref\":
27+
\"#/definitions/fields\"\n },\n {\n \"$ref\":
28+
\"#/definitions/ml_model_output\"\n }\n ]\n },\n
29+
\ \"assets\": {\n \"$comment\": \"This validates the fields
30+
in Item Assets (including in Raster Band Objects), but does not require them.\",\n
31+
\ \"type\": \"object\",\n \"additionalProperties\": {\n \"allOf\":
32+
[\n {\n \"$ref\": \"#/definitions/fields\"\n },\n
33+
\ {\n \"$ref\": \"#/definitions/raster_bands\"\n
34+
\ },\n {\n \"$ref\": \"#/definitions/ml_model_output\"\n
35+
\ }\n ]\n }\n }\n }\n },\n
36+
\ {\n \"$comment\": \"This is the schema for STAC Collections.\",\n
37+
\ \"type\": \"object\",\n \"required\": [\"type\"],\n \"properties\":
38+
{\n \"type\": {\n \"const\": \"Collection\"\n },\n
39+
\ \"assets\": {\n \"$comment\": \"This validates the fields
40+
in Collection Assets, but does not require them.\",\n \"type\": \"object\",\n
41+
\ \"additionalProperties\": {\n \"allOf\": [\n {\n
42+
\ \"$ref\": \"#/definitions/fields\"\n },\n {\n
43+
\ \"$ref\": \"#/definitions/raster_bands\"\n },\n
44+
\ {\n \"$ref\": \"#/definitions/ml_model_output\"\n
45+
\ }\n ]\n }\n },\n \"item_assets\":
46+
{\n \"$comment\": \"This validates the fields in Item Asset Definitions,
47+
but does not require them.\",\n \"type\": \"object\",\n \"additionalProperties\":
48+
{\n \"allOf\": [\n {\n \"$ref\": \"#/definitions/fields\"\n
49+
\ },\n {\n \"$ref\": \"#/definitions/raster_bands\"\n
50+
\ },\n {\n \"$ref\": \"#/definitions/ml_model_output\"\n
51+
\ }\n ]\n }\n },\n \"summaries\":
52+
{\n \"$comment\": \"This validates the fields in Summaries, but does
53+
not require them.\",\n \"$ref\": \"#/definitions/fields\"\n }\n
54+
\ }\n }\n ],\n \"definitions\": {\n \"require_any_field\": {\n
55+
\ \"$comment\": \"Please list all fields here so that we can force the
56+
existance of one of them in other parts of the schemas.\",\n \"anyOf\":
57+
[\n {\n \"required\": [\"classification:bitfields\"]\n },\n
58+
\ {\n \"required\": [\"classification:classes\"]\n }\n
59+
\ ]\n },\n \"fields\": {\n \"$comment\": \"Add your new fields
60+
here. Don't require them here, do that above in the corresponding schema.\",\n
61+
\ \"type\": \"object\",\n \"properties\": {\n \"classification:bitfields\":
62+
{\n \"type\": \"array\",\n \"uniqueItems\": true,\n \"minItems\":
63+
1,\n \"items\": {\n \"$ref\": \"#/definitions/bit_field_object\"\n
64+
\ }\n },\n \"classification:classes\": {\n \"type\":
65+
\"array\",\n \"uniqueItems\": true,\n \"minItems\": 1,\n
66+
\ \"items\": {\n \"$ref\": \"#/definitions/class_object\"\n
67+
\ }\n }\n },\n \"patternProperties\": {\n \"^(?!classification:)\":
68+
{}\n },\n \"additionalProperties\": false\n },\n \"class_object\":
69+
{\n \"$comment\": \"Object for storing classes\",\n \"type\": \"object\",\n
70+
\ \"required\": [\"value\", \"name\"],\n \"properties\": {\n \"value\":
71+
{\n \"type\": \"integer\"\n },\n \"description\": {\n
72+
\ \"type\": \"string\"\n },\n \"name\": {\n \"type\":
73+
\"string\",\n \"pattern\": \"^[0-9A-Za-z-_]+$\"\n },\n \"title\":
74+
{\n \"type\": \"string\"\n },\n \"color_hint\": {\n
75+
\ \"type\": \"string\",\n \"pattern\": \"^([0-9A-Fa-f]{6})$\"\n
76+
\ },\n \"nodata\": {\n \"type\": \"boolean\"\n },\n
77+
\ \"percentage\": {\n \"type\": \"number\",\n \"minimum\":
78+
0,\n \"maximum\": 100\n },\n \"count\": {\n \"type\":
79+
\"integer\",\n \"minimum\": 0\n }\n }\n },\n \"bit_field_object\":
80+
{\n \"$comment\": \"Object for storing bit fields\",\n \"type\":
81+
\"object\",\n \"required\": [\"offset\", \"length\", \"classes\"],\n
82+
\ \"properties\": {\n \"offset\": {\n \"type\": \"integer\",\n
83+
\ \"minimum\": 0\n },\n \"length\": {\n \"type\":
84+
\"integer\",\n \"minimum\": 1\n },\n \"classes\": {\n
85+
\ \"type\": \"array\",\n \"uniqueItems\": true,\n \"minItems\":
86+
1,\n \"items\": {\n \"$ref\": \"#/definitions/class_object\"\n
87+
\ }\n },\n \"roles\": {\n \"type\": \"array\",\n
88+
\ \"uniqueItems\": true,\n \"minItems\": 1,\n \"items\":
89+
{\n \"type\": \"string\"\n }\n },\n \"description\":
90+
{\n \"type\": \"string\"\n },\n \"name\": {\n \"type\":
91+
\"string\",\n \"pattern\": \"^[0-9A-Za-z-_]+$\"\n }\n }\n
92+
\ },\n \"raster_bands\": {\n \"$comment\": \"Classification fields
93+
on the Raster Extension raster:bands object\",\n \"type\": \"object\",\n
94+
\ \"properties\": {\n \"raster:bands\": {\n \"type\":
95+
\"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n
96+
\ }\n }\n }\n },\n \"ml_model_output\": {\n \"$comment\":
97+
\"Classification fields on the MLM Extension mlm:output objects (https://crim-ca.github.io/mlm-extension/v1.0.0/schema.json).\",\n
98+
\ \"description\": \"Describes the classes embedded in the output of the
99+
ML model following inference.\",\n \"type\": \"object\",\n \"properties\":
100+
{\n \"mlm:output\": {\n \"type\": \"array\",\n \"items\":
101+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
102+
\ }\n }\n }\n}\n"
103+
headers:
104+
Accept-Ranges:
105+
- bytes
106+
Access-Control-Allow-Origin:
107+
- '*'
108+
Age:
109+
- '0'
110+
Cache-Control:
111+
- max-age=600
112+
Connection:
113+
- close
114+
Content-Length:
115+
- '6554'
116+
Content-Type:
117+
- application/json; charset=utf-8
118+
Date:
119+
- Tue, 17 Dec 2024 23:25:05 GMT
120+
ETag:
121+
- '"66487a48-199a"'
122+
Last-Modified:
123+
- Sat, 18 May 2024 09:52:08 GMT
124+
Server:
125+
- GitHub.com
126+
Strict-Transport-Security:
127+
- max-age=31556952
128+
Vary:
129+
- Accept-Encoding
130+
Via:
131+
- 1.1 varnish
132+
X-Cache:
133+
- MISS
134+
X-Cache-Hits:
135+
- '0'
136+
X-Fastly-Request-ID:
137+
- eaacd335ebd5f2b35eecf0fbe0ad4f9d82ef2870
138+
X-GitHub-Request-Id:
139+
- CB53:15BE6F:C16B48:D70A6A:67620851
140+
X-Served-By:
141+
- cache-den-kden1300056-DEN
142+
X-Timer:
143+
- S1734477906.551532,VS0,VE74
144+
expires:
145+
- Tue, 17 Dec 2024 23:35:05 GMT
146+
permissions-policy:
147+
- interest-cohort=()
148+
x-proxy-cache:
149+
- MISS
150+
status:
151+
code: 200
152+
message: OK
153+
version: 1

tests/extensions/test_classification.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,25 @@ def test_apply_bitfields(plain_item: Item) -> None:
162162
)
163163

164164

165+
@pytest.mark.vcr()
166+
def test_apply_classes(plain_item: Item) -> None:
167+
ClassificationExtension.add_to(plain_item)
168+
ClassificationExtension.ext(plain_item).apply(
169+
classes=[
170+
Classification.create(name="no", value=0),
171+
Classification.create(name="yes", value=1),
172+
]
173+
)
174+
plain_item.validate()
175+
assert (
176+
ClassificationExtension.ext(plain_item).classes is not None
177+
and len(
178+
cast(list[Classification], ClassificationExtension.ext(plain_item).classes)
179+
)
180+
== 2
181+
)
182+
183+
165184
def test_create_classes(plain_item: Item) -> None:
166185
ClassificationExtension.add_to(plain_item)
167186
ext = ClassificationExtension.ext(plain_item)

0 commit comments

Comments
 (0)