Skip to content

Commit cec0386

Browse files
authored
Merge branch 'main' into issues/856-datacube
2 parents 9febf44 + b40f3be commit cec0386

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- Interactions between **pytest-recording** and the validator schema cache ([#1242](https://github.com/stac-utils/pystac/pull/1242))
2222
- Call `registry` when instantiating `Draft7Validator` ([#1240](https://github.com/stac-utils/pystac/pull/1240))
2323
- Migration for the classification, datacube, table, and timestamps extensions ([#1258](https://github.com/stac-utils/pystac/pull/1258))
24+
- Handling of `bboxes` and `intervals` arguments to `SpatialExtent` and `TemporalExtent`, respectively ([#1268](https://github.com/stac-utils/pystac/pull/1268))
2425

2526
### Removed
2627

pystac/collection.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
C = TypeVar("C", bound="Collection")
4242

43+
Bboxes = list[list[Union[float, int]]]
4344
TemporalIntervals = Union[list[list[datetime]], list[list[Optional[datetime]]]]
4445
TemporalIntervalsLike = Union[
4546
TemporalIntervals, list[datetime], list[Optional[datetime]]
@@ -59,7 +60,7 @@ class SpatialExtent:
5960
Spatial Extent object.
6061
"""
6162

62-
bboxes: list[list[float]]
63+
bboxes: Bboxes
6364
"""A list of bboxes that represent the spatial
6465
extent of the collection. Each bbox can be 2D or 3D. The length of the bbox
6566
array must be 2*n where n is the number of dimensions. For example, a
@@ -71,15 +72,18 @@ class SpatialExtent:
7172

7273
def __init__(
7374
self,
74-
bboxes: list[list[float]] | list[float],
75+
bboxes: Bboxes | list[float | int],
7576
extra_fields: dict[str, Any] | None = None,
7677
) -> None:
78+
if not isinstance(bboxes, list):
79+
raise TypeError("bboxes must be a list")
80+
7781
# A common mistake is to pass in a single bbox instead of a list of bboxes.
7882
# Account for this by transforming the input in that case.
79-
if isinstance(bboxes, list) and isinstance(bboxes[0], float):
80-
self.bboxes: list[list[float]] = [cast(list[float], bboxes)]
83+
if isinstance(bboxes[0], (float, int)):
84+
self.bboxes = [cast(list[Union[float, int]], bboxes)]
8185
else:
82-
self.bboxes = cast(list[list[float]], bboxes)
86+
self.bboxes = cast(Bboxes, bboxes)
8387

8488
self.extra_fields = extra_fields or {}
8589

@@ -196,16 +200,18 @@ class TemporalExtent:
196200

197201
def __init__(
198202
self,
199-
intervals: TemporalIntervals,
203+
intervals: TemporalIntervals | list[datetime | None],
200204
extra_fields: dict[str, Any] | None = None,
201205
):
206+
if not isinstance(intervals, list):
207+
raise TypeError("intervals must be a list")
202208
# A common mistake is to pass in a single interval instead of a
203209
# list of intervals. Account for this by transforming the input
204210
# in that case.
205-
if isinstance(intervals, list) and isinstance(intervals[0], datetime):
206-
self.intervals = intervals
211+
if isinstance(intervals[0], datetime) or intervals[0] is None:
212+
self.intervals = [cast(list[Optional[datetime]], intervals)]
207213
else:
208-
self.intervals = intervals
214+
self.intervals = cast(TemporalIntervals, intervals)
209215

210216
self.extra_fields = extra_fields or {}
211217

pystac/extensions/base.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def validate_owner_has_extension(
181181
``None``.
182182
"""
183183
warnings.warn(
184-
"ensure_owner_has_extension is deprecated and will be removed in v1.9. "
184+
"ensure_owner_has_extension is deprecated. "
185185
"Use ensure_owner_has_extension instead",
186186
DeprecationWarning,
187187
)
@@ -234,8 +234,7 @@ def validate_has_extension(cls, obj: S, add_if_missing: bool = False) -> None:
234234
not already present. Defaults to False.
235235
"""
236236
warnings.warn(
237-
"validate_has_extension is deprecated and will be removed in v1.9. "
238-
"Use ensure_has_extension instead",
237+
"validate_has_extension is deprecated. Use ensure_has_extension instead",
239238
DeprecationWarning,
240239
)
241240

tests/test_collection.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,31 @@ def test_temporal_extent_init_typing(self) -> None:
381381

382382
_ = TemporalExtent([[start_datetime, end_datetime]])
383383

384+
@pytest.mark.block_network()
385+
def test_temporal_extent_allows_single_interval(self) -> None:
386+
start_datetime = str_to_datetime("2022-01-01T00:00:00Z")
387+
end_datetime = str_to_datetime("2022-01-31T23:59:59Z")
388+
389+
interval = [start_datetime, end_datetime]
390+
temporal_extent = TemporalExtent(intervals=interval) # type: ignore
391+
392+
self.assertEqual(temporal_extent.intervals, [interval])
393+
394+
@pytest.mark.block_network()
395+
def test_temporal_extent_allows_single_interval_open_start(self) -> None:
396+
end_datetime = str_to_datetime("2022-01-31T23:59:59Z")
397+
398+
interval = [None, end_datetime]
399+
temporal_extent = TemporalExtent(intervals=interval)
400+
401+
self.assertEqual(temporal_extent.intervals, [interval])
402+
403+
@pytest.mark.block_network()
404+
def test_temporal_extent_non_list_intervals_fails(self) -> None:
405+
with pytest.raises(TypeError):
406+
# Pass in non-list intervals
407+
_ = TemporalExtent(intervals=1) # type: ignore
408+
384409
@pytest.mark.block_network()
385410
def test_spatial_allows_single_bbox(self) -> None:
386411
temporal_extent = TemporalExtent(intervals=[[TEST_DATETIME, None]])
@@ -399,6 +424,12 @@ def test_spatial_allows_single_bbox(self) -> None:
399424

400425
collection.validate()
401426

427+
@pytest.mark.block_network()
428+
def test_spatial_extent_non_list_bboxes_fails(self) -> None:
429+
with pytest.raises(TypeError):
430+
# Pass in non-list bboxes
431+
_ = SpatialExtent(bboxes=1) # type: ignore
432+
402433
def test_from_items(self) -> None:
403434
item1 = Item(
404435
id="test-item-1",

0 commit comments

Comments
 (0)