pystac-ext-mgrs 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pystac_ext_mgrs-1.0.0/.gitignore +163 -0
- pystac_ext_mgrs-1.0.0/PKG-INFO +37 -0
- pystac_ext_mgrs-1.0.0/README.md +13 -0
- pystac_ext_mgrs-1.0.0/pyproject.toml +36 -0
- pystac_ext_mgrs-1.0.0/pystac/extensions/mgrs.py +252 -0
- pystac_ext_mgrs-1.0.0/pystac/extensions/py.typed +0 -0
- pystac_ext_mgrs-1.0.0/tests/cassettes/test_mgrs/test_set_field[grid_square-ZA].yaml +52 -0
- pystac_ext_mgrs-1.0.0/tests/cassettes/test_mgrs/test_set_field[latitude_band-C].yaml +52 -0
- pystac_ext_mgrs-1.0.0/tests/cassettes/test_mgrs/test_set_field[utm_zone-59].yaml +52 -0
- pystac_ext_mgrs-1.0.0/tests/cassettes/test_mgrs/test_validate.yaml +52 -0
- pystac_ext_mgrs-1.0.0/tests/data-files/item.json +53 -0
- pystac_ext_mgrs-1.0.0/tests/test_mgrs.py +140 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
*.pyc
|
|
2
|
+
*.egg-info
|
|
3
|
+
*.eggs
|
|
4
|
+
.DS_Store
|
|
5
|
+
data
|
|
6
|
+
config.json
|
|
7
|
+
stdout*
|
|
8
|
+
/integration*
|
|
9
|
+
.idea
|
|
10
|
+
.vscode
|
|
11
|
+
.actrc
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Sphinx documentation
|
|
15
|
+
.ipynb_checkpoints/
|
|
16
|
+
|
|
17
|
+
docs/tutorials/pystac-example*
|
|
18
|
+
docs/tutorials/spacenet-stac/
|
|
19
|
+
docs/tutorials/spacenet-cog-stac/
|
|
20
|
+
docs/tutorials/data/
|
|
21
|
+
docs/quickstart_stac/
|
|
22
|
+
|
|
23
|
+
# Byte-compiled / optimized / DLL files
|
|
24
|
+
__pycache__/
|
|
25
|
+
*.py[cod]
|
|
26
|
+
*$py.class
|
|
27
|
+
|
|
28
|
+
# C extensions
|
|
29
|
+
*.so
|
|
30
|
+
|
|
31
|
+
# Distribution / packaging
|
|
32
|
+
.Python
|
|
33
|
+
build/
|
|
34
|
+
develop-eggs/
|
|
35
|
+
dist/
|
|
36
|
+
downloads/
|
|
37
|
+
eggs/
|
|
38
|
+
.eggs/
|
|
39
|
+
lib/
|
|
40
|
+
lib64/
|
|
41
|
+
parts/
|
|
42
|
+
sdist/
|
|
43
|
+
var/
|
|
44
|
+
wheels/
|
|
45
|
+
share/python-wheels/
|
|
46
|
+
*.egg-info/
|
|
47
|
+
.installed.cfg
|
|
48
|
+
*.egg
|
|
49
|
+
MANIFEST
|
|
50
|
+
|
|
51
|
+
# PyInstaller
|
|
52
|
+
# Usually these files are written by a python script from a template
|
|
53
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
54
|
+
*.manifest
|
|
55
|
+
*.spec
|
|
56
|
+
|
|
57
|
+
# Installer logs
|
|
58
|
+
pip-log.txt
|
|
59
|
+
pip-delete-this-directory.txt
|
|
60
|
+
|
|
61
|
+
# Unit test / coverage reports
|
|
62
|
+
htmlcov/
|
|
63
|
+
.tox/
|
|
64
|
+
.nox/
|
|
65
|
+
.coverage
|
|
66
|
+
.coverage.*
|
|
67
|
+
.cache
|
|
68
|
+
nosetests.xml
|
|
69
|
+
coverage.xml
|
|
70
|
+
*.cover
|
|
71
|
+
*.py,cover
|
|
72
|
+
.hypothesis/
|
|
73
|
+
.pytest_cache/
|
|
74
|
+
cover/
|
|
75
|
+
|
|
76
|
+
# Translations
|
|
77
|
+
*.mo
|
|
78
|
+
*.pot
|
|
79
|
+
|
|
80
|
+
# Django stuff:
|
|
81
|
+
*.log
|
|
82
|
+
local_settings.py
|
|
83
|
+
db.sqlite3
|
|
84
|
+
db.sqlite3-journal
|
|
85
|
+
|
|
86
|
+
# Flask stuff:
|
|
87
|
+
instance/
|
|
88
|
+
.webassets-cache
|
|
89
|
+
|
|
90
|
+
# Scrapy stuff:
|
|
91
|
+
.scrapy
|
|
92
|
+
|
|
93
|
+
# Sphinx documentation
|
|
94
|
+
docs/_build/
|
|
95
|
+
|
|
96
|
+
# PyBuilder
|
|
97
|
+
.pybuilder/
|
|
98
|
+
target/
|
|
99
|
+
|
|
100
|
+
# Jupyter Notebook
|
|
101
|
+
.ipynb_checkpoints
|
|
102
|
+
|
|
103
|
+
# IPython
|
|
104
|
+
profile_default/
|
|
105
|
+
ipython_config.py
|
|
106
|
+
|
|
107
|
+
# pyenv
|
|
108
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
109
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
110
|
+
# .python-version
|
|
111
|
+
|
|
112
|
+
# pipenv
|
|
113
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
114
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
115
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
116
|
+
# install all needed dependencies.
|
|
117
|
+
# Pipfile.lock
|
|
118
|
+
|
|
119
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
120
|
+
__pypackages__/
|
|
121
|
+
|
|
122
|
+
# Celery stuff
|
|
123
|
+
celerybeat-schedule
|
|
124
|
+
celerybeat.pid
|
|
125
|
+
|
|
126
|
+
# SageMath parsed files
|
|
127
|
+
*.sage.py
|
|
128
|
+
|
|
129
|
+
# Environments
|
|
130
|
+
.env
|
|
131
|
+
.venv
|
|
132
|
+
env/
|
|
133
|
+
venv/
|
|
134
|
+
ENV/
|
|
135
|
+
env.bak/
|
|
136
|
+
venv.bak/
|
|
137
|
+
|
|
138
|
+
# Spyder project settings
|
|
139
|
+
.spyderproject
|
|
140
|
+
.spyproject
|
|
141
|
+
|
|
142
|
+
# Rope project settings
|
|
143
|
+
.ropeproject
|
|
144
|
+
|
|
145
|
+
# mkdocs documentation
|
|
146
|
+
/site
|
|
147
|
+
|
|
148
|
+
# mypy
|
|
149
|
+
.mypy_cache/
|
|
150
|
+
.dmypy.json
|
|
151
|
+
dmypy.json
|
|
152
|
+
|
|
153
|
+
# Pyre type checker
|
|
154
|
+
.pyre/
|
|
155
|
+
|
|
156
|
+
# pytype static type analyzer
|
|
157
|
+
.pytype/
|
|
158
|
+
|
|
159
|
+
# Cython debug symbols
|
|
160
|
+
cython_debug/
|
|
161
|
+
|
|
162
|
+
# asv environments
|
|
163
|
+
.asv
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pystac-ext-mgrs
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: MGRS extension for PySTAC
|
|
5
|
+
Project-URL: Documentation, https://pystac.readthedocs.io
|
|
6
|
+
Project-URL: Repository, https://github.com/stac-utils/pystac
|
|
7
|
+
Project-URL: Issues, https://github.com/stac-utils/pystac/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/stac-utils/pystac/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Discussions, https://github.com/radiantearth/stac-spec/discussions/categories/stac-software
|
|
10
|
+
License: Apache-2.0
|
|
11
|
+
Keywords: STAC,catalog,imagery,mgrs,pystac,raster
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: pystac-core
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# pystac-ext-mgrs
|
|
26
|
+
|
|
27
|
+
[PySTAC](https://pypi.org/project/pystac/) extension package for the [MGRS Extension](https://github.com/stac-extensions/mgrs).
|
|
28
|
+
This extension provides fields for describing data using the Military Grid Reference System (MGRS), including UTM zone, latitude band, and grid square identifiers.
|
|
29
|
+
|
|
30
|
+
## Supported versions
|
|
31
|
+
|
|
32
|
+
- [v1.0.0](https://stac-extensions.github.io/mgrs/v1.0.0/schema.json)
|
|
33
|
+
|
|
34
|
+
## Versioning
|
|
35
|
+
|
|
36
|
+
This package's version corresponds to the version of the extension specification it targets.
|
|
37
|
+
When we release updates to the package code without changing the target extension version, we use [post releases](https://packaging.python.org/en/latest/discussions/versioning/#post-releases), e.g. `1.0.0.post1`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# pystac-ext-mgrs
|
|
2
|
+
|
|
3
|
+
[PySTAC](https://pypi.org/project/pystac/) extension package for the [MGRS Extension](https://github.com/stac-extensions/mgrs).
|
|
4
|
+
This extension provides fields for describing data using the Military Grid Reference System (MGRS), including UTM zone, latitude band, and grid square identifiers.
|
|
5
|
+
|
|
6
|
+
## Supported versions
|
|
7
|
+
|
|
8
|
+
- [v1.0.0](https://stac-extensions.github.io/mgrs/v1.0.0/schema.json)
|
|
9
|
+
|
|
10
|
+
## Versioning
|
|
11
|
+
|
|
12
|
+
This package's version corresponds to the version of the extension specification it targets.
|
|
13
|
+
When we release updates to the package code without changing the target extension version, we use [post releases](https://packaging.python.org/en/latest/discussions/versioning/#post-releases), e.g. `1.0.0.post1`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pystac-ext-mgrs"
|
|
3
|
+
description = "MGRS extension for PySTAC"
|
|
4
|
+
readme = "README.md"
|
|
5
|
+
version = "1.0.0"
|
|
6
|
+
authors = []
|
|
7
|
+
maintainers = []
|
|
8
|
+
keywords = ["pystac", "imagery", "raster", "catalog", "STAC", "mgrs"]
|
|
9
|
+
license = { text = "Apache-2.0" }
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 5 - Production/Stable",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"License :: OSI Approved :: Apache Software License",
|
|
14
|
+
"Natural Language :: English",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
]
|
|
21
|
+
requires-python = ">=3.10"
|
|
22
|
+
dependencies = ["pystac-core"]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Documentation = "https://pystac.readthedocs.io"
|
|
26
|
+
Repository = "https://github.com/stac-utils/pystac"
|
|
27
|
+
Issues = "https://github.com/stac-utils/pystac/issues"
|
|
28
|
+
Changelog = "https://github.com/stac-utils/pystac/blob/main/CHANGELOG.md"
|
|
29
|
+
Discussions = "https://github.com/radiantearth/stac-spec/discussions/categories/stac-software"
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["hatchling"]
|
|
33
|
+
build-backend = "hatchling.build"
|
|
34
|
+
|
|
35
|
+
[tool.hatch.build.targets.wheel]
|
|
36
|
+
packages = ["pystac"]
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"""Implements the :stac-ext:`MGRS Extension <mgrs>`."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from re import Pattern
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
import pystac
|
|
8
|
+
from pystac.extensions.base import ExtensionManagementMixin, PropertiesExtension
|
|
9
|
+
from pystac.extensions.hooks import ExtensionHooks
|
|
10
|
+
|
|
11
|
+
SCHEMA_URI: str = "https://stac-extensions.github.io/mgrs/v1.0.0/schema.json"
|
|
12
|
+
SCHEMA_STARTSWITH: str = "https://stac-extensions.github.io/mgrs/"
|
|
13
|
+
PREFIX: str = "mgrs:"
|
|
14
|
+
|
|
15
|
+
# Field names
|
|
16
|
+
LATITUDE_BAND_PROP: str = PREFIX + "latitude_band" # required
|
|
17
|
+
GRID_SQUARE_PROP: str = PREFIX + "grid_square" # required
|
|
18
|
+
UTM_ZONE_PROP: str = PREFIX + "utm_zone"
|
|
19
|
+
|
|
20
|
+
LATITUDE_BANDS: frozenset[str] = frozenset(
|
|
21
|
+
{
|
|
22
|
+
"C",
|
|
23
|
+
"D",
|
|
24
|
+
"E",
|
|
25
|
+
"F",
|
|
26
|
+
"G",
|
|
27
|
+
"H",
|
|
28
|
+
"J",
|
|
29
|
+
"K",
|
|
30
|
+
"L",
|
|
31
|
+
"M",
|
|
32
|
+
"N",
|
|
33
|
+
"P",
|
|
34
|
+
"Q",
|
|
35
|
+
"R",
|
|
36
|
+
"S",
|
|
37
|
+
"T",
|
|
38
|
+
"U",
|
|
39
|
+
"V",
|
|
40
|
+
"W",
|
|
41
|
+
"X",
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
UTM_ZONES: frozenset[int] = frozenset(
|
|
46
|
+
{
|
|
47
|
+
1,
|
|
48
|
+
2,
|
|
49
|
+
3,
|
|
50
|
+
4,
|
|
51
|
+
5,
|
|
52
|
+
6,
|
|
53
|
+
7,
|
|
54
|
+
8,
|
|
55
|
+
9,
|
|
56
|
+
10,
|
|
57
|
+
11,
|
|
58
|
+
12,
|
|
59
|
+
13,
|
|
60
|
+
14,
|
|
61
|
+
15,
|
|
62
|
+
16,
|
|
63
|
+
17,
|
|
64
|
+
18,
|
|
65
|
+
19,
|
|
66
|
+
20,
|
|
67
|
+
21,
|
|
68
|
+
22,
|
|
69
|
+
23,
|
|
70
|
+
24,
|
|
71
|
+
25,
|
|
72
|
+
26,
|
|
73
|
+
27,
|
|
74
|
+
28,
|
|
75
|
+
29,
|
|
76
|
+
30,
|
|
77
|
+
31,
|
|
78
|
+
32,
|
|
79
|
+
33,
|
|
80
|
+
34,
|
|
81
|
+
35,
|
|
82
|
+
36,
|
|
83
|
+
37,
|
|
84
|
+
38,
|
|
85
|
+
39,
|
|
86
|
+
40,
|
|
87
|
+
41,
|
|
88
|
+
42,
|
|
89
|
+
43,
|
|
90
|
+
44,
|
|
91
|
+
45,
|
|
92
|
+
46,
|
|
93
|
+
47,
|
|
94
|
+
48,
|
|
95
|
+
49,
|
|
96
|
+
50,
|
|
97
|
+
51,
|
|
98
|
+
52,
|
|
99
|
+
53,
|
|
100
|
+
54,
|
|
101
|
+
55,
|
|
102
|
+
56,
|
|
103
|
+
57,
|
|
104
|
+
58,
|
|
105
|
+
59,
|
|
106
|
+
60,
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
GRID_SQUARE_REGEX: str = (
|
|
111
|
+
r"[ABCDEFGHJKLMNPQRSTUVWXYZ][ABCDEFGHJKLMNPQRSTUV](\d{2}|\d{4}|\d{6}|\d{8}|\d{10})?"
|
|
112
|
+
)
|
|
113
|
+
GRID_SQUARE_PATTERN: Pattern[str] = re.compile(GRID_SQUARE_REGEX)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def validated_latitude_band(v: str) -> str:
|
|
117
|
+
if not isinstance(v, str):
|
|
118
|
+
raise ValueError("Invalid MGRS latitude band: must be str")
|
|
119
|
+
if v not in LATITUDE_BANDS:
|
|
120
|
+
raise ValueError(f"Invalid MGRS latitude band: {v} is not in {LATITUDE_BANDS}")
|
|
121
|
+
return v
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def validated_grid_square(v: str) -> str:
|
|
125
|
+
if not isinstance(v, str):
|
|
126
|
+
raise ValueError("Invalid MGRS grid square identifier: must be str")
|
|
127
|
+
if not GRID_SQUARE_PATTERN.fullmatch(v):
|
|
128
|
+
raise ValueError(
|
|
129
|
+
f"Invalid MGRS grid square identifier: {v}"
|
|
130
|
+
f" does not match the regex {GRID_SQUARE_REGEX}"
|
|
131
|
+
)
|
|
132
|
+
return v
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def validated_utm_zone(v: int | None) -> int | None:
|
|
136
|
+
if v is not None and not isinstance(v, int):
|
|
137
|
+
raise ValueError("Invalid MGRS utm zone: must be None or int")
|
|
138
|
+
if v is not None and v not in UTM_ZONES:
|
|
139
|
+
raise ValueError(f"Invalid MGRS UTM zone: {v} is not in {UTM_ZONES}")
|
|
140
|
+
return v
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class MgrsExtension(
|
|
144
|
+
PropertiesExtension,
|
|
145
|
+
ExtensionManagementMixin[pystac.Item | pystac.Collection],
|
|
146
|
+
):
|
|
147
|
+
"""A concrete implementation of :class:`~pystac.extensions.mgrs.MgrsExtension`
|
|
148
|
+
on an :class:`~pystac.Item`
|
|
149
|
+
that extends the properties of the Item to include properties defined in the
|
|
150
|
+
:stac-ext:`MGRS Extension <mgrs>`.
|
|
151
|
+
|
|
152
|
+
This class should generally not be instantiated directly. Instead, call
|
|
153
|
+
:meth:`~pystac.extensions.mgrs.MgrsExtension.ext` on an :class:`~pystac.Item`
|
|
154
|
+
to extend it.
|
|
155
|
+
|
|
156
|
+
.. code-block:: python
|
|
157
|
+
|
|
158
|
+
>>> item: pystac.Item = ...
|
|
159
|
+
>>> proj_ext = MgrsExtension.ext(item)
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
name: Literal["mgrs"] = "mgrs"
|
|
163
|
+
item: pystac.Item
|
|
164
|
+
"""The :class:`~pystac.Item` being extended."""
|
|
165
|
+
|
|
166
|
+
properties: dict[str, Any]
|
|
167
|
+
"""The :class:`~pystac.Item` properties, including extension properties."""
|
|
168
|
+
|
|
169
|
+
def __init__(self, item: pystac.Item):
|
|
170
|
+
self.item = item
|
|
171
|
+
self.properties = item.properties
|
|
172
|
+
|
|
173
|
+
def __repr__(self) -> str:
|
|
174
|
+
return f"<ItemMgrsExtension Item id={self.item.id}>"
|
|
175
|
+
|
|
176
|
+
def apply(
|
|
177
|
+
self,
|
|
178
|
+
latitude_band: str,
|
|
179
|
+
grid_square: str,
|
|
180
|
+
utm_zone: int | None = None,
|
|
181
|
+
) -> None:
|
|
182
|
+
"""Applies MGRS extension properties to the extended Item.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
latitude_band : REQUIRED. The latitude band of the Item's centroid.
|
|
186
|
+
grid_square : REQUIRED. MGRS grid square of the Item's centroid.
|
|
187
|
+
utm_zone : The UTM Zone of the Item centroid.
|
|
188
|
+
"""
|
|
189
|
+
self.latitude_band = validated_latitude_band(latitude_band)
|
|
190
|
+
self.grid_square = validated_grid_square(grid_square)
|
|
191
|
+
self.utm_zone = validated_utm_zone(utm_zone)
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def latitude_band(self) -> str | None:
|
|
195
|
+
"""Get or sets the latitude band of the datasource."""
|
|
196
|
+
return self._get_property(LATITUDE_BAND_PROP, str)
|
|
197
|
+
|
|
198
|
+
@latitude_band.setter
|
|
199
|
+
def latitude_band(self, v: str) -> None:
|
|
200
|
+
self._set_property(
|
|
201
|
+
LATITUDE_BAND_PROP, validated_latitude_band(v), pop_if_none=False
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def grid_square(self) -> str | None:
|
|
206
|
+
"""Get or sets the latitude band of the datasource."""
|
|
207
|
+
return self._get_property(GRID_SQUARE_PROP, str)
|
|
208
|
+
|
|
209
|
+
@grid_square.setter
|
|
210
|
+
def grid_square(self, v: str) -> None:
|
|
211
|
+
self._set_property(
|
|
212
|
+
GRID_SQUARE_PROP, validated_grid_square(v), pop_if_none=False
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def utm_zone(self) -> int | None:
|
|
217
|
+
"""Get or sets the latitude band of the datasource."""
|
|
218
|
+
return self._get_property(UTM_ZONE_PROP, int)
|
|
219
|
+
|
|
220
|
+
@utm_zone.setter
|
|
221
|
+
def utm_zone(self, v: int | None) -> None:
|
|
222
|
+
self._set_property(UTM_ZONE_PROP, validated_utm_zone(v), pop_if_none=True)
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def get_schema_uri(cls) -> str:
|
|
226
|
+
return SCHEMA_URI
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def ext(cls, obj: pystac.Item, add_if_missing: bool = False) -> "MgrsExtension":
|
|
230
|
+
"""Extends the given STAC Object with properties from the :stac-ext:`MGRS
|
|
231
|
+
Extension <mgrs>`.
|
|
232
|
+
|
|
233
|
+
This extension can be applied to instances of :class:`~pystac.Item`.
|
|
234
|
+
|
|
235
|
+
Raises:
|
|
236
|
+
|
|
237
|
+
pystac.ExtensionTypeError : If an invalid object type is passed.
|
|
238
|
+
"""
|
|
239
|
+
if isinstance(obj, pystac.Item):
|
|
240
|
+
cls.ensure_has_extension(obj, add_if_missing)
|
|
241
|
+
return MgrsExtension(obj)
|
|
242
|
+
else:
|
|
243
|
+
raise pystac.ExtensionTypeError(cls._ext_error_message(obj))
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class MgrsExtensionHooks(ExtensionHooks):
|
|
247
|
+
schema_uri: str = SCHEMA_URI
|
|
248
|
+
prev_extension_ids: set[str] = set()
|
|
249
|
+
stac_object_types = {pystac.STACObjectType.ITEM}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
MGRS_EXTENSION_HOOKS: ExtensionHooks = MgrsExtensionHooks()
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
body: null
|
|
4
|
+
headers: {}
|
|
5
|
+
method: GET
|
|
6
|
+
uri: https://stac-extensions.github.io/mgrs/v1.0.0/schema.json
|
|
7
|
+
response:
|
|
8
|
+
body:
|
|
9
|
+
string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\":
|
|
10
|
+
\"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json#\",\n \"title\":
|
|
11
|
+
\"MGRS Extension\",\n \"description\": \"STAC MGRS Extension for STAC Items.\",\n
|
|
12
|
+
\ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Items.\",\n
|
|
13
|
+
\ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\":
|
|
14
|
+
[\n \"type\",\n \"properties\",\n \"assets\"\n
|
|
15
|
+
\ ],\n \"properties\": {\n \"type\": {\n \"const\":
|
|
16
|
+
\"Feature\"\n },\n \"properties\": {\n \"allOf\":
|
|
17
|
+
[\n {\n \"$comment\": \"Require fields here
|
|
18
|
+
for item properties.\",\n \"required\": [\n \"mgrs:latitude_band\",\n
|
|
19
|
+
\ \"mgrs:grid_square\"\n ]\n },\n
|
|
20
|
+
\ {\n \"$ref\": \"#/definitions/fields\"\n
|
|
21
|
+
\ }\n ]\n },\n \"assets\":
|
|
22
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
23
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
24
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
25
|
+
\ }\n ]\n },\n {\n \"$comment\": \"This is the schema
|
|
26
|
+
for STAC Collections.\",\n \"allOf\": [\n {\n \"type\":
|
|
27
|
+
\"object\",\n \"required\": [\n \"type\"\n ],\n
|
|
28
|
+
\ \"properties\": {\n \"type\": {\n \"const\":
|
|
29
|
+
\"Collection\"\n },\n \"assets\": {\n \"type\":
|
|
30
|
+
\"object\",\n \"additionalProperties\": {\n \"$ref\":
|
|
31
|
+
\"#/definitions/fields\"\n }\n },\n \"item_assets\":
|
|
32
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
33
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
34
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
35
|
+
\ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\":
|
|
36
|
+
{\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n
|
|
37
|
+
\ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\":
|
|
38
|
+
\"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json\"\n
|
|
39
|
+
\ }\n }\n }\n },\n \"fields\": {\n \"$comment\":
|
|
40
|
+
\"Add your new fields here. Don't require them here, do that above in the
|
|
41
|
+
item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"mgrs:latitude_band\":
|
|
42
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:grid_square\":
|
|
43
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:utm_zone\":
|
|
44
|
+
{\n \"type\": \"integer\"\n }\n },\n \"patternProperties\":
|
|
45
|
+
{\n \"^(?!mgrs:)\": {\n \"$comment\": \"Do not allow other
|
|
46
|
+
fields with this prefix\"\n }\n },\n \"additionalProperties\":
|
|
47
|
+
false\n }\n }\n}"
|
|
48
|
+
headers: {}
|
|
49
|
+
status:
|
|
50
|
+
code: 200
|
|
51
|
+
message: OK
|
|
52
|
+
version: 1
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
body: null
|
|
4
|
+
headers: {}
|
|
5
|
+
method: GET
|
|
6
|
+
uri: https://stac-extensions.github.io/mgrs/v1.0.0/schema.json
|
|
7
|
+
response:
|
|
8
|
+
body:
|
|
9
|
+
string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\":
|
|
10
|
+
\"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json#\",\n \"title\":
|
|
11
|
+
\"MGRS Extension\",\n \"description\": \"STAC MGRS Extension for STAC Items.\",\n
|
|
12
|
+
\ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Items.\",\n
|
|
13
|
+
\ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\":
|
|
14
|
+
[\n \"type\",\n \"properties\",\n \"assets\"\n
|
|
15
|
+
\ ],\n \"properties\": {\n \"type\": {\n \"const\":
|
|
16
|
+
\"Feature\"\n },\n \"properties\": {\n \"allOf\":
|
|
17
|
+
[\n {\n \"$comment\": \"Require fields here
|
|
18
|
+
for item properties.\",\n \"required\": [\n \"mgrs:latitude_band\",\n
|
|
19
|
+
\ \"mgrs:grid_square\"\n ]\n },\n
|
|
20
|
+
\ {\n \"$ref\": \"#/definitions/fields\"\n
|
|
21
|
+
\ }\n ]\n },\n \"assets\":
|
|
22
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
23
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
24
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
25
|
+
\ }\n ]\n },\n {\n \"$comment\": \"This is the schema
|
|
26
|
+
for STAC Collections.\",\n \"allOf\": [\n {\n \"type\":
|
|
27
|
+
\"object\",\n \"required\": [\n \"type\"\n ],\n
|
|
28
|
+
\ \"properties\": {\n \"type\": {\n \"const\":
|
|
29
|
+
\"Collection\"\n },\n \"assets\": {\n \"type\":
|
|
30
|
+
\"object\",\n \"additionalProperties\": {\n \"$ref\":
|
|
31
|
+
\"#/definitions/fields\"\n }\n },\n \"item_assets\":
|
|
32
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
33
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
34
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
35
|
+
\ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\":
|
|
36
|
+
{\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n
|
|
37
|
+
\ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\":
|
|
38
|
+
\"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json\"\n
|
|
39
|
+
\ }\n }\n }\n },\n \"fields\": {\n \"$comment\":
|
|
40
|
+
\"Add your new fields here. Don't require them here, do that above in the
|
|
41
|
+
item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"mgrs:latitude_band\":
|
|
42
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:grid_square\":
|
|
43
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:utm_zone\":
|
|
44
|
+
{\n \"type\": \"integer\"\n }\n },\n \"patternProperties\":
|
|
45
|
+
{\n \"^(?!mgrs:)\": {\n \"$comment\": \"Do not allow other
|
|
46
|
+
fields with this prefix\"\n }\n },\n \"additionalProperties\":
|
|
47
|
+
false\n }\n }\n}"
|
|
48
|
+
headers: {}
|
|
49
|
+
status:
|
|
50
|
+
code: 200
|
|
51
|
+
message: OK
|
|
52
|
+
version: 1
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
body: null
|
|
4
|
+
headers: {}
|
|
5
|
+
method: GET
|
|
6
|
+
uri: https://stac-extensions.github.io/mgrs/v1.0.0/schema.json
|
|
7
|
+
response:
|
|
8
|
+
body:
|
|
9
|
+
string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\":
|
|
10
|
+
\"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json#\",\n \"title\":
|
|
11
|
+
\"MGRS Extension\",\n \"description\": \"STAC MGRS Extension for STAC Items.\",\n
|
|
12
|
+
\ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Items.\",\n
|
|
13
|
+
\ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\":
|
|
14
|
+
[\n \"type\",\n \"properties\",\n \"assets\"\n
|
|
15
|
+
\ ],\n \"properties\": {\n \"type\": {\n \"const\":
|
|
16
|
+
\"Feature\"\n },\n \"properties\": {\n \"allOf\":
|
|
17
|
+
[\n {\n \"$comment\": \"Require fields here
|
|
18
|
+
for item properties.\",\n \"required\": [\n \"mgrs:latitude_band\",\n
|
|
19
|
+
\ \"mgrs:grid_square\"\n ]\n },\n
|
|
20
|
+
\ {\n \"$ref\": \"#/definitions/fields\"\n
|
|
21
|
+
\ }\n ]\n },\n \"assets\":
|
|
22
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
23
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
24
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
25
|
+
\ }\n ]\n },\n {\n \"$comment\": \"This is the schema
|
|
26
|
+
for STAC Collections.\",\n \"allOf\": [\n {\n \"type\":
|
|
27
|
+
\"object\",\n \"required\": [\n \"type\"\n ],\n
|
|
28
|
+
\ \"properties\": {\n \"type\": {\n \"const\":
|
|
29
|
+
\"Collection\"\n },\n \"assets\": {\n \"type\":
|
|
30
|
+
\"object\",\n \"additionalProperties\": {\n \"$ref\":
|
|
31
|
+
\"#/definitions/fields\"\n }\n },\n \"item_assets\":
|
|
32
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
33
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
34
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
35
|
+
\ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\":
|
|
36
|
+
{\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n
|
|
37
|
+
\ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\":
|
|
38
|
+
\"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json\"\n
|
|
39
|
+
\ }\n }\n }\n },\n \"fields\": {\n \"$comment\":
|
|
40
|
+
\"Add your new fields here. Don't require them here, do that above in the
|
|
41
|
+
item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"mgrs:latitude_band\":
|
|
42
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:grid_square\":
|
|
43
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:utm_zone\":
|
|
44
|
+
{\n \"type\": \"integer\"\n }\n },\n \"patternProperties\":
|
|
45
|
+
{\n \"^(?!mgrs:)\": {\n \"$comment\": \"Do not allow other
|
|
46
|
+
fields with this prefix\"\n }\n },\n \"additionalProperties\":
|
|
47
|
+
false\n }\n }\n}"
|
|
48
|
+
headers: {}
|
|
49
|
+
status:
|
|
50
|
+
code: 200
|
|
51
|
+
message: OK
|
|
52
|
+
version: 1
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
interactions:
|
|
2
|
+
- request:
|
|
3
|
+
body: null
|
|
4
|
+
headers: {}
|
|
5
|
+
method: GET
|
|
6
|
+
uri: https://stac-extensions.github.io/mgrs/v1.0.0/schema.json
|
|
7
|
+
response:
|
|
8
|
+
body:
|
|
9
|
+
string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\":
|
|
10
|
+
\"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json#\",\n \"title\":
|
|
11
|
+
\"MGRS Extension\",\n \"description\": \"STAC MGRS Extension for STAC Items.\",\n
|
|
12
|
+
\ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Items.\",\n
|
|
13
|
+
\ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\":
|
|
14
|
+
[\n \"type\",\n \"properties\",\n \"assets\"\n
|
|
15
|
+
\ ],\n \"properties\": {\n \"type\": {\n \"const\":
|
|
16
|
+
\"Feature\"\n },\n \"properties\": {\n \"allOf\":
|
|
17
|
+
[\n {\n \"$comment\": \"Require fields here
|
|
18
|
+
for item properties.\",\n \"required\": [\n \"mgrs:latitude_band\",\n
|
|
19
|
+
\ \"mgrs:grid_square\"\n ]\n },\n
|
|
20
|
+
\ {\n \"$ref\": \"#/definitions/fields\"\n
|
|
21
|
+
\ }\n ]\n },\n \"assets\":
|
|
22
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
23
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
24
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
25
|
+
\ }\n ]\n },\n {\n \"$comment\": \"This is the schema
|
|
26
|
+
for STAC Collections.\",\n \"allOf\": [\n {\n \"type\":
|
|
27
|
+
\"object\",\n \"required\": [\n \"type\"\n ],\n
|
|
28
|
+
\ \"properties\": {\n \"type\": {\n \"const\":
|
|
29
|
+
\"Collection\"\n },\n \"assets\": {\n \"type\":
|
|
30
|
+
\"object\",\n \"additionalProperties\": {\n \"$ref\":
|
|
31
|
+
\"#/definitions/fields\"\n }\n },\n \"item_assets\":
|
|
32
|
+
{\n \"type\": \"object\",\n \"additionalProperties\":
|
|
33
|
+
{\n \"$ref\": \"#/definitions/fields\"\n }\n }\n
|
|
34
|
+
\ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n
|
|
35
|
+
\ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\":
|
|
36
|
+
{\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n
|
|
37
|
+
\ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\":
|
|
38
|
+
\"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json\"\n
|
|
39
|
+
\ }\n }\n }\n },\n \"fields\": {\n \"$comment\":
|
|
40
|
+
\"Add your new fields here. Don't require them here, do that above in the
|
|
41
|
+
item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"mgrs:latitude_band\":
|
|
42
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:grid_square\":
|
|
43
|
+
{\n \"type\": \"string\"\n },\n \"mgrs:utm_zone\":
|
|
44
|
+
{\n \"type\": \"integer\"\n }\n },\n \"patternProperties\":
|
|
45
|
+
{\n \"^(?!mgrs:)\": {\n \"$comment\": \"Do not allow other
|
|
46
|
+
fields with this prefix\"\n }\n },\n \"additionalProperties\":
|
|
47
|
+
false\n }\n }\n}"
|
|
48
|
+
headers: {}
|
|
49
|
+
status:
|
|
50
|
+
code: 200
|
|
51
|
+
message: OK
|
|
52
|
+
version: 1
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"stac_version": "1.1.0",
|
|
3
|
+
"stac_extensions": [
|
|
4
|
+
"https://stac-extensions.github.io/mgrs/v1.0.0/schema.json"
|
|
5
|
+
],
|
|
6
|
+
"type": "Feature",
|
|
7
|
+
"id": "item",
|
|
8
|
+
"bbox": [
|
|
9
|
+
172.9,
|
|
10
|
+
1.3,
|
|
11
|
+
173,
|
|
12
|
+
1.4
|
|
13
|
+
],
|
|
14
|
+
"geometry": {
|
|
15
|
+
"type": "Polygon",
|
|
16
|
+
"coordinates": [
|
|
17
|
+
[
|
|
18
|
+
[
|
|
19
|
+
172.9,
|
|
20
|
+
1.3
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
173,
|
|
24
|
+
1.3
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
173,
|
|
28
|
+
1.4
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
172.9,
|
|
32
|
+
1.4
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
172.9,
|
|
36
|
+
1.3
|
|
37
|
+
]
|
|
38
|
+
]
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"properties": {
|
|
42
|
+
"datetime": "2020-12-11T22:38:32Z",
|
|
43
|
+
"mgrs:utm_zone": 13,
|
|
44
|
+
"mgrs:latitude_band": "X",
|
|
45
|
+
"mgrs:grid_square": "DH"
|
|
46
|
+
},
|
|
47
|
+
"links": [],
|
|
48
|
+
"assets": {
|
|
49
|
+
"data": {
|
|
50
|
+
"href": "https://example.com/examples/file.xyz"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Tests for pystac.tests.extensions.mgrs"""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
import pystac
|
|
9
|
+
from pystac.extensions.mgrs import MgrsExtension
|
|
10
|
+
|
|
11
|
+
DATA_FILES = Path(__file__).resolve().parent / "data-files"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.fixture
|
|
15
|
+
def ext_item_uri() -> str:
|
|
16
|
+
return str(DATA_FILES / "item.json")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture
|
|
20
|
+
def ext_item(ext_item_uri: str) -> pystac.Item:
|
|
21
|
+
return pystac.Item.from_file(ext_item_uri)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_stac_extensions(ext_item: pystac.Item) -> None:
|
|
25
|
+
assert MgrsExtension.has_extension(ext_item)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_get_schema_uri(ext_item: pystac.Item) -> None:
|
|
29
|
+
assert MgrsExtension.get_schema_uri() in ext_item.stac_extensions
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_ext_raises_if_item_does_not_conform(item: pystac.Item) -> None:
|
|
33
|
+
with pytest.raises(pystac.errors.ExtensionNotImplemented):
|
|
34
|
+
MgrsExtension.ext(item)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_ext_raises_on_collection(collection: pystac.Collection) -> None:
|
|
38
|
+
with pytest.raises(
|
|
39
|
+
pystac.errors.ExtensionTypeError,
|
|
40
|
+
match="MgrsExtension does not apply to type 'Collection'",
|
|
41
|
+
) as e:
|
|
42
|
+
MgrsExtension.ext(collection) # type: ignore
|
|
43
|
+
assert "Hint" not in str(e.value)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_to_from_dict(ext_item_uri: str, ext_item: pystac.Item) -> None:
|
|
47
|
+
with open(ext_item_uri) as f:
|
|
48
|
+
d = json.load(f)
|
|
49
|
+
actual = ext_item.to_dict(include_self_link=False)
|
|
50
|
+
assert actual == d
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_add_to(item: pystac.Item) -> None:
|
|
54
|
+
assert not MgrsExtension.has_extension(item)
|
|
55
|
+
MgrsExtension.add_to(item)
|
|
56
|
+
|
|
57
|
+
assert MgrsExtension.has_extension(item)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_apply(item: pystac.Item) -> None:
|
|
61
|
+
MgrsExtension.add_to(item)
|
|
62
|
+
MgrsExtension.ext(item).apply(latitude_band="X", grid_square="DH")
|
|
63
|
+
assert MgrsExtension.ext(item).latitude_band
|
|
64
|
+
assert MgrsExtension.ext(item).grid_square
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_apply_without_required_fields_raises(item: pystac.Item) -> None:
|
|
68
|
+
MgrsExtension.add_to(item)
|
|
69
|
+
with pytest.raises(TypeError, match="missing 2 required positional arguments"):
|
|
70
|
+
MgrsExtension.ext(item).apply() # type: ignore
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@pytest.mark.vcr()
|
|
74
|
+
def test_validate(ext_item: pystac.Item) -> None:
|
|
75
|
+
assert ext_item.validate()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.mark.parametrize("field", ["latitude_band", "grid_square", "utm_zone"])
|
|
79
|
+
def test_get_field(ext_item: pystac.Item, field: str) -> None:
|
|
80
|
+
prop = ext_item.properties[f"mgrs:{field}"]
|
|
81
|
+
attr = getattr(MgrsExtension.ext(ext_item), field)
|
|
82
|
+
|
|
83
|
+
assert attr is not None
|
|
84
|
+
assert attr == prop
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.vcr()
|
|
88
|
+
@pytest.mark.parametrize(
|
|
89
|
+
"field,value",
|
|
90
|
+
[
|
|
91
|
+
("latitude_band", "C"),
|
|
92
|
+
("grid_square", "ZA"),
|
|
93
|
+
("utm_zone", 59),
|
|
94
|
+
],
|
|
95
|
+
)
|
|
96
|
+
def test_set_field(ext_item: pystac.Item, field: str, value) -> None: # type: ignore
|
|
97
|
+
original = ext_item.properties[f"mgrs:{field}"]
|
|
98
|
+
setattr(MgrsExtension.ext(ext_item), field, value)
|
|
99
|
+
new = ext_item.properties[f"mgrs:{field}"]
|
|
100
|
+
|
|
101
|
+
assert new != original
|
|
102
|
+
assert new == value
|
|
103
|
+
assert ext_item.validate()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_utm_zone_set_to_none_pops_from_dict(ext_item: pystac.Item) -> None:
|
|
107
|
+
assert "mgrs:utm_zone" in ext_item.properties
|
|
108
|
+
|
|
109
|
+
MgrsExtension.ext(ext_item).utm_zone = None
|
|
110
|
+
assert "mgrs:utm_zone" not in ext_item.properties
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_invalid_latitude_band_raises_informative_error(ext_item: pystac.Item) -> None:
|
|
114
|
+
with pytest.raises(ValueError, match="must be str"):
|
|
115
|
+
MgrsExtension.ext(ext_item).latitude_band = 2 # type: ignore
|
|
116
|
+
|
|
117
|
+
with pytest.raises(ValueError, match="must be str"):
|
|
118
|
+
MgrsExtension.ext(ext_item).latitude_band = None # type: ignore
|
|
119
|
+
|
|
120
|
+
with pytest.raises(ValueError, match="a is not in "):
|
|
121
|
+
MgrsExtension.ext(ext_item).latitude_band = "a"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_invalid_grid_square_raises_informative_error(ext_item: pystac.Item) -> None:
|
|
125
|
+
with pytest.raises(ValueError, match="must be str"):
|
|
126
|
+
MgrsExtension.ext(ext_item).grid_square = 2 # type: ignore
|
|
127
|
+
|
|
128
|
+
with pytest.raises(ValueError, match="must be str"):
|
|
129
|
+
MgrsExtension.ext(ext_item).grid_square = None # type: ignore
|
|
130
|
+
|
|
131
|
+
with pytest.raises(ValueError, match="nv does not match the regex "):
|
|
132
|
+
MgrsExtension.ext(ext_item).grid_square = "nv"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_invalid_utm_zone_raises_informative_error(ext_item: pystac.Item) -> None:
|
|
136
|
+
with pytest.raises(ValueError, match="must be None or int"):
|
|
137
|
+
MgrsExtension.ext(ext_item).utm_zone = "foo" # type: ignore
|
|
138
|
+
|
|
139
|
+
with pytest.raises(ValueError, match="61 is not in "):
|
|
140
|
+
MgrsExtension.ext(ext_item).utm_zone = 61
|