oapi-profile-builder 2.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.
- oapi_profile_builder-2.0.0/LICENSE +17 -0
- oapi_profile_builder-2.0.0/PKG-INFO +612 -0
- oapi_profile_builder-2.0.0/README.md +567 -0
- oapi_profile_builder-2.0.0/pyproject.toml +42 -0
- oapi_profile_builder-2.0.0/setup.cfg +4 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/__init__.py +28 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/cite.py +446 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/cite_features.py +363 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/cli.py +209 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/compile.py +75 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/generate.py +867 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/models.py +272 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder/server_validation.py +120 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder.egg-info/PKG-INFO +612 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder.egg-info/SOURCES.txt +17 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder.egg-info/dependency_links.txt +1 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder.egg-info/entry_points.txt +2 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder.egg-info/requires.txt +7 -0
- oapi_profile_builder-2.0.0/src/oapi_profile_builder.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2025 NOAA/NWS/Meteorological Development Laboratory
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oapi-profile-builder
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Authoritative tooling for creating OGC API Service Profiles (EDR, Features)
|
|
5
|
+
Author-email: Shane Mill <shane.mill@noaa.gov>
|
|
6
|
+
License: Apache License
|
|
7
|
+
Version 2.0, January 2004
|
|
8
|
+
http://www.apache.org/licenses/
|
|
9
|
+
|
|
10
|
+
Copyright 2025 NOAA/NWS/Meteorological Development Laboratory
|
|
11
|
+
|
|
12
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
you may not use this file except in compliance with the License.
|
|
14
|
+
You may obtain a copy of the License at
|
|
15
|
+
|
|
16
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
|
|
18
|
+
Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
See the License for the specific language governing permissions and
|
|
22
|
+
limitations under the License.
|
|
23
|
+
|
|
24
|
+
Project-URL: Homepage, https://github.com/ShaneMill1/OGC-API-Service-Profile-Builder
|
|
25
|
+
Project-URL: Issues, https://github.com/ShaneMill1/OGC-API-Service-Profile-Builder/issues
|
|
26
|
+
Keywords: ogc,edr,features,environmental-data-retrieval,profile,openapi,asyncapi
|
|
27
|
+
Classifier: Development Status :: 4 - Beta
|
|
28
|
+
Classifier: Intended Audience :: Science/Research
|
|
29
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
30
|
+
Classifier: Programming Language :: Python :: 3
|
|
31
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
34
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
35
|
+
Requires-Python: >=3.10
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
License-File: LICENSE
|
|
38
|
+
Requires-Dist: edr-pydantic>=0.3
|
|
39
|
+
Requires-Dist: pydantic>=2.0
|
|
40
|
+
Requires-Dist: pyyaml>=6.0
|
|
41
|
+
Requires-Dist: requests>=2.31
|
|
42
|
+
Provides-Extra: validate
|
|
43
|
+
Requires-Dist: schemathesis>=3.0; extra == "validate"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# OGC API Service Profile Builder
|
|
47
|
+
|
|
48
|
+
Authoritative tooling for creating OGC API Service Profiles (EDR, Features), built on Pydantic and [edr-pydantic](https://github.com/KNMI/edr-pydantic).
|
|
49
|
+
|
|
50
|
+
## Overview
|
|
51
|
+
|
|
52
|
+
Profile structure is defined as Pydantic models (`src/oapi_profile_builder/models.py`). Instantiating a `ServiceProfile` validates the entire profile — cross-model validators catch referential errors — before any files are written.
|
|
53
|
+
|
|
54
|
+
Collections use `edr-pydantic`'s authoritative `Collection` model directly, meaning a profile config is simultaneously a valid EDR collection descriptor and a Part 3 profile definition.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install oapi-profile-builder
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Workflow
|
|
65
|
+
|
|
66
|
+
### 1. Author a Profile Config
|
|
67
|
+
|
|
68
|
+
A profile config is a YAML or JSON file. Start with the minimal example:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cp examples/minimal_profile.yaml my_profile.yaml
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The minimal valid config:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
name: my_profile
|
|
78
|
+
title: My EDR Profile
|
|
79
|
+
|
|
80
|
+
# OGC API - EDR Part 3 compliance fields (recommended)
|
|
81
|
+
required_conformance_classes:
|
|
82
|
+
- "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/core"
|
|
83
|
+
|
|
84
|
+
extent_requirements:
|
|
85
|
+
minimum_bbox: [-180, -90, 180, 90]
|
|
86
|
+
allowed_crs:
|
|
87
|
+
- "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
|
|
88
|
+
|
|
89
|
+
output_formats:
|
|
90
|
+
- name: GeoJSON
|
|
91
|
+
media_type: application/geo+json
|
|
92
|
+
schema_ref: https://geojson.org/schema/FeatureCollection.json
|
|
93
|
+
|
|
94
|
+
collections:
|
|
95
|
+
- id: my_collection
|
|
96
|
+
links:
|
|
97
|
+
- href: https://example.com/collections/my_collection
|
|
98
|
+
rel: self
|
|
99
|
+
type: application/json
|
|
100
|
+
extent:
|
|
101
|
+
spatial:
|
|
102
|
+
bbox:
|
|
103
|
+
- [-180, -90, 180, 90]
|
|
104
|
+
crs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
|
|
105
|
+
parameter_names:
|
|
106
|
+
temp:
|
|
107
|
+
type: Parameter
|
|
108
|
+
observedProperty:
|
|
109
|
+
label: Temperature
|
|
110
|
+
unit: # REQUIRED per OGC API - EDR Part 3
|
|
111
|
+
label: Celsius
|
|
112
|
+
symbol: C
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
See [`examples/minimal_profile.yaml`](examples/minimal_profile.yaml) for a complete working example and [`examples/nwsviz_profile.yaml`](examples/nwsviz_profile.yaml) for a full profile with 13 collections, 3 processes, requirements, abstract tests, and document metadata.
|
|
116
|
+
|
|
117
|
+
### 2. Generate Profile Artifacts
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
oapi-profile-builder generate \
|
|
121
|
+
--config my_profile.yaml \
|
|
122
|
+
--output ./my_profile
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Produces:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
my_profile/
|
|
129
|
+
├── openapi.yaml
|
|
130
|
+
├── profile_config.json
|
|
131
|
+
├── document.adoc # Metanorma root document
|
|
132
|
+
├── sections/
|
|
133
|
+
│ ├── 00-abstract.adoc
|
|
134
|
+
│ ├── 01-preface.adoc
|
|
135
|
+
│ ├── 02-scope.adoc
|
|
136
|
+
│ ├── 03-conformance.adoc
|
|
137
|
+
│ ├── 04-references.adoc
|
|
138
|
+
│ ├── 05-terms.adoc
|
|
139
|
+
│ ├── 06-requirements.adoc
|
|
140
|
+
│ └── 07-abstract-tests.adoc
|
|
141
|
+
├── requirements/
|
|
142
|
+
│ ├── requirements_class_core.adoc
|
|
143
|
+
│ └── core/REQ_<id>.adoc
|
|
144
|
+
└── abstract_tests/
|
|
145
|
+
├── ATS_class_core.adoc
|
|
146
|
+
└── core/ATS_<id>.adoc
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Validate a config without generating output:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
oapi-profile-builder validate --config my_profile.yaml
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 3. Compile OGC PDF
|
|
156
|
+
|
|
157
|
+
Requires Docker. Shells out to the official `metanorma/metanorma` image — no Ruby or LaTeX install needed.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
oapi-profile-builder generate \
|
|
161
|
+
--config my_profile.yaml \
|
|
162
|
+
--output ./my_profile \
|
|
163
|
+
--pdf
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The `document_metadata` block in the profile config drives the Metanorma document header:
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
document_metadata:
|
|
170
|
+
doc_number: "24-nwsviz"
|
|
171
|
+
doc_subtype: implementation
|
|
172
|
+
copyright_year: 2026
|
|
173
|
+
editors:
|
|
174
|
+
- Shane Mill
|
|
175
|
+
submitting_orgs:
|
|
176
|
+
- NOAA/NWS/MDL
|
|
177
|
+
keywords:
|
|
178
|
+
- ogcdoc
|
|
179
|
+
- OGC API
|
|
180
|
+
- EDR
|
|
181
|
+
- NWSViz
|
|
182
|
+
- service profile
|
|
183
|
+
external_id: http://www.opengis.net/doc/dp/ogcapi-edr-nwsviz/1.0
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Produces `my_profile/document.pdf` — a fully compliant OGC `draft-standard` PDF with Abstract, Preface, Scope, Conformance, References, Terms, Requirements class, and normative Abstract Test Suite annex.
|
|
187
|
+
|
|
188
|
+
### 4. Validate Against a Live Server
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
oapi-profile-builder validate-server \
|
|
192
|
+
--config my_profile.yaml \
|
|
193
|
+
--url https://edr-api-desi-c.mdl.nws.noaa.gov \
|
|
194
|
+
--max-examples 3
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Results:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
Operations: 100 selected / 106 total
|
|
201
|
+
Tested: 47
|
|
202
|
+
Test cases: 1002 generated, 1002 passed
|
|
203
|
+
|
|
204
|
+
No issues found in 49.51s
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Use `--stateful` to additionally test job lifecycle endpoints (`/jobs/{jobId}`, `DELETE /jobs/{jobId}`) via POST `/execution` chaining.
|
|
208
|
+
|
|
209
|
+
Add `collection_examples` to your config to supply real `instanceId` values for schemathesis path parameters:
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
collection_examples:
|
|
213
|
+
my_collection:
|
|
214
|
+
instanceId: "2025-04-02T00:00:00Z"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 5. OGC CITE Conformance Testing
|
|
218
|
+
|
|
219
|
+
#### EDR Conformance Testing
|
|
220
|
+
|
|
221
|
+
Run the official OGC API - EDR Part 1 conformance test suite (ets-ogcapi-edr10):
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
oapi-profile-builder cite-test \
|
|
225
|
+
--url https://edr-api-desi-c.mdl.nws.noaa.gov \
|
|
226
|
+
--report ./cite_results
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Results:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
OGC API - EDR CITE Results
|
|
233
|
+
Passed: 76/84
|
|
234
|
+
Failed: 0
|
|
235
|
+
Skipped: 8
|
|
236
|
+
|
|
237
|
+
✓ All CITE tests passed.
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The tool automatically:
|
|
241
|
+
- Clones and builds ets-ogcapi-edr10 from GitHub on first run
|
|
242
|
+
- Caches Docker image (`ogccite/ets-ogcapi-edr10:local`) for subsequent runs
|
|
243
|
+
- Runs TestNG tests via `docker exec`
|
|
244
|
+
- Supports localhost testing with `--network host` mode
|
|
245
|
+
- Generates JSON report with detailed test results
|
|
246
|
+
|
|
247
|
+
The skipped tests are optional features not implemented by the server.
|
|
248
|
+
|
|
249
|
+
#### Features Conformance Testing
|
|
250
|
+
|
|
251
|
+
Run the official OGC API - Features Part 1 conformance test suite (ets-ogcapi-features10):
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
oapi-profile-builder cite-test-features \
|
|
255
|
+
--url https://api.example.com \
|
|
256
|
+
--report ./cite_features_results
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Results:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
OGC API - Features CITE Results
|
|
263
|
+
Passed: 639/712
|
|
264
|
+
Failed: 18
|
|
265
|
+
Skipped: 55
|
|
266
|
+
|
|
267
|
+
✗ 18 test(s) failed.
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The tool automatically:
|
|
271
|
+
- Pulls pre-built Docker image (`ogccite/ets-ogcapi-features10:latest`) from Docker Hub
|
|
272
|
+
- Runs TestNG tests via `docker exec`
|
|
273
|
+
- Supports localhost testing with `--network host` mode
|
|
274
|
+
- Generates JSON report with detailed test results
|
|
275
|
+
|
|
276
|
+
The skipped tests are optional features not implemented by the server.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Config Reference
|
|
281
|
+
|
|
282
|
+
### Top-level fields
|
|
283
|
+
|
|
284
|
+
| Field | Type | Required | Description |
|
|
285
|
+
|---|---|---|---|
|
|
286
|
+
| `name` | `string` | yes | Lowercase identifier using only `a-z`, `0-9`, `_`. Used in OGC URIs and OpenAPI `operationId`s. e.g. `water_gauge` |
|
|
287
|
+
| `title` | `string` | yes | Human-readable profile title |
|
|
288
|
+
| `version` | `string` | no | Profile version. Defaults to `1.0` |
|
|
289
|
+
| `server_url` | `string` | no | Base URL of the live server (for documentation only - not used in profile OpenAPI per OGC API - EDR Part 3) |
|
|
290
|
+
| `collections` | `list` | yes | One or more EDR collections (see below) |
|
|
291
|
+
| `processes` | `list` | no | OGC API Processes to include in the OpenAPI (see below) |
|
|
292
|
+
| `requirements` | `list` | no | Normative requirements (see below) |
|
|
293
|
+
| `abstract_tests` | `list` | no | Conformance tests — each must reference a valid requirement `id` (see below) |
|
|
294
|
+
| `pubsub` | `object` | no | OGC API - EDR Part 2 PubSub configuration (see below) |
|
|
295
|
+
| `collection_examples` | `object` | no | Map of collection id → example parameter values (e.g. `instanceId`) for server validation |
|
|
296
|
+
| `document_metadata` | `object` | no | Metanorma document header fields for PDF compilation (see below) |
|
|
297
|
+
| `required_conformance_classes` | `list[string]` | no | Conformance classes that implementations must declare. Defaults to EDR Core |
|
|
298
|
+
| `extent_requirements` | `object` | no | Profile-level extent restrictions (see below) |
|
|
299
|
+
| `output_formats` | `list` | no | Profile-level output format definitions with schema references (see below) |
|
|
300
|
+
| `collection_id_pattern` | `string` | no | Regex pattern for valid collection IDs |
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### `collections[]`
|
|
305
|
+
|
|
306
|
+
Each collection uses the [edr-pydantic](https://github.com/KNMI/edr-pydantic) `Collection` schema — the same model an EDR server returns at `/collections/{id}`. Key fields:
|
|
307
|
+
|
|
308
|
+
| Field | Type | Required | Description |
|
|
309
|
+
|---|---|---|---|
|
|
310
|
+
| `id` | `string` | yes | Collection identifier |
|
|
311
|
+
| `title` | `string` | no | Human-readable collection name |
|
|
312
|
+
| `description` | `string` | no | Collection description |
|
|
313
|
+
| `links` | `list` | yes | At minimum a `self` link |
|
|
314
|
+
| `extent.spatial.bbox` | `list` | yes | Bounding box as `[[minLon, minLat, maxLon, maxLat]]` |
|
|
315
|
+
| `extent.spatial.crs` | `string` | yes | CRS URI, typically `http://www.opengis.net/def/crs/OGC/1.3/CRS84` |
|
|
316
|
+
| `data_queries` | `object` | no | Which EDR query types this collection supports |
|
|
317
|
+
| `output_formats` | `list` | no | Supported output format labels e.g. `GeoJSON`, `CoverageJSON` |
|
|
318
|
+
| `parameter_names` | `object` | no | Map of parameter id → `Parameter` object |
|
|
319
|
+
|
|
320
|
+
#### `data_queries`
|
|
321
|
+
|
|
322
|
+
Supported keys: `items` · `position` · `area` · `radius` · `cube` · `trajectory` · `corridor` · `locations` · `instances`
|
|
323
|
+
|
|
324
|
+
```yaml
|
|
325
|
+
data_queries:
|
|
326
|
+
position:
|
|
327
|
+
link:
|
|
328
|
+
href: https://example.com/collections/water_gauge/position
|
|
329
|
+
rel: data
|
|
330
|
+
variables:
|
|
331
|
+
query_type: position
|
|
332
|
+
output_formats:
|
|
333
|
+
- CoverageJSON
|
|
334
|
+
items:
|
|
335
|
+
link:
|
|
336
|
+
href: https://example.com/collections/water_gauge/items
|
|
337
|
+
rel: data
|
|
338
|
+
variables:
|
|
339
|
+
query_type: items
|
|
340
|
+
output_formats:
|
|
341
|
+
- GeoJSON
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### `parameter_names`
|
|
345
|
+
|
|
346
|
+
**Note:** Per OGC API - EDR Part 3 requirements, all parameters must specify `unit` and `observedProperty`. The tool validates this automatically.
|
|
347
|
+
|
|
348
|
+
```yaml
|
|
349
|
+
parameter_names:
|
|
350
|
+
gauge_height:
|
|
351
|
+
type: Parameter
|
|
352
|
+
observedProperty:
|
|
353
|
+
label: Gauge Height
|
|
354
|
+
unit:
|
|
355
|
+
label: feet
|
|
356
|
+
symbol: ft
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
### `extent_requirements`
|
|
362
|
+
|
|
363
|
+
Profile-level extent restrictions per OGC API - EDR Part 3 REQ_extent.
|
|
364
|
+
|
|
365
|
+
| Field | Type | Required | Description |
|
|
366
|
+
|---|---|---|---|
|
|
367
|
+
| `minimum_bbox` | `list[float]` | yes | Minimum spatial bounds `[minLon, minLat, maxLon, maxLat]` |
|
|
368
|
+
| `allowed_crs` | `list[string]` | no | Enumerated list of valid CRS values |
|
|
369
|
+
| `crs_pattern` | `string` | no | Regular expression defining valid CRS string patterns |
|
|
370
|
+
| `allowed_trs` | `list[string]` | no | Enumerated list of valid TRS values |
|
|
371
|
+
| `trs_pattern` | `string` | no | Regular expression defining valid TRS string patterns |
|
|
372
|
+
| `allowed_vrs` | `list[string]` | no | Enumerated list of valid VRS values |
|
|
373
|
+
| `vrs_pattern` | `string` | no | Regular expression defining valid VRS string patterns |
|
|
374
|
+
|
|
375
|
+
**Note:** Either `allowed_crs` or `crs_pattern` must be specified.
|
|
376
|
+
|
|
377
|
+
```yaml
|
|
378
|
+
extent_requirements:
|
|
379
|
+
minimum_bbox: [-180, -90, 180, 90]
|
|
380
|
+
allowed_crs:
|
|
381
|
+
- "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
|
|
382
|
+
- "http://www.opengis.net/def/crs/EPSG/0/4326"
|
|
383
|
+
allowed_trs:
|
|
384
|
+
- "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian"
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
### `output_formats[]`
|
|
390
|
+
|
|
391
|
+
Profile-level output format definitions with schema references per OGC API - EDR Part 3 REQ_output-format.
|
|
392
|
+
|
|
393
|
+
| Field | Type | Required | Description |
|
|
394
|
+
|---|---|---|---|
|
|
395
|
+
| `name` | `string` | yes | Format name (e.g., GeoJSON, CoverageJSON) |
|
|
396
|
+
| `media_type` | `string` | yes | MIME type (e.g., application/geo+json) |
|
|
397
|
+
| `schema_ref` | `string` | no | URL to schema definition |
|
|
398
|
+
|
|
399
|
+
```yaml
|
|
400
|
+
output_formats:
|
|
401
|
+
- name: GeoJSON
|
|
402
|
+
media_type: application/geo+json
|
|
403
|
+
schema_ref: https://geojson.org/schema/FeatureCollection.json
|
|
404
|
+
- name: CoverageJSON
|
|
405
|
+
media_type: application/prs.coverage+json
|
|
406
|
+
schema_ref: https://schemas.opengis.net/ogcapi/edr/1.0/openapi/schemas/coverageJSON.yaml
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
### `required_conformance_classes[]`
|
|
412
|
+
|
|
413
|
+
Conformance classes that implementations must declare at `/conformance` per OGC API - EDR Part 3 REQ_api.
|
|
414
|
+
|
|
415
|
+
Defaults to:
|
|
416
|
+
```yaml
|
|
417
|
+
required_conformance_classes:
|
|
418
|
+
- "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/core"
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Add additional conformance classes as needed:
|
|
422
|
+
```yaml
|
|
423
|
+
required_conformance_classes:
|
|
424
|
+
- "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/core"
|
|
425
|
+
- "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/oas30"
|
|
426
|
+
- "http://www.opengis.net/spec/ogcapi-edr-2/1.0/conf/pubsub"
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
### `processes[]`
|
|
432
|
+
|
|
433
|
+
OGC API Processes to expose in the generated OpenAPI. Each entry produces `/processes/{id}` and `/processes/{id}/execution` paths, plus `/processes`, `/jobs`, `/jobs/{jobId}`, and `/jobs/{jobId}/results`.
|
|
434
|
+
|
|
435
|
+
| Field | Type | Required | Description |
|
|
436
|
+
|---|---|---|---|
|
|
437
|
+
| `id` | `string` | yes | Process identifier e.g. `edr-zarr-difference` |
|
|
438
|
+
| `title` | `string` | no | Human-readable process name |
|
|
439
|
+
| `description` | `string` | no | Process description |
|
|
440
|
+
| `output_content` | `object` | no | OpenAPI content map for the 200 response. Defaults to `application/json` |
|
|
441
|
+
|
|
442
|
+
```yaml
|
|
443
|
+
processes:
|
|
444
|
+
- id: edr-zarr-difference
|
|
445
|
+
title: EDR Zarr Dataset Difference
|
|
446
|
+
description: Calculates the difference between two EDR Zarr datasets.
|
|
447
|
+
output_content:
|
|
448
|
+
application/zip:
|
|
449
|
+
schema:
|
|
450
|
+
type: object
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
### `requirements[]`
|
|
456
|
+
|
|
457
|
+
| Field | Type | Required | Description |
|
|
458
|
+
|---|---|---|---|
|
|
459
|
+
| `id` | `string` | yes | Lowercase, hyphen-separated. Must match `^[a-z0-9][a-z0-9\-]*$` |
|
|
460
|
+
| `statement` | `string` | yes | One-sentence normative statement |
|
|
461
|
+
| `parts` | `list[string]` | yes | One or more SHALL/MUST clauses |
|
|
462
|
+
|
|
463
|
+
```yaml
|
|
464
|
+
requirements:
|
|
465
|
+
- id: position-coveragejson
|
|
466
|
+
statement: The position query SHALL return CoverageJSON.
|
|
467
|
+
parts:
|
|
468
|
+
- The service SHALL provide a /collections/{id}/position endpoint.
|
|
469
|
+
- The response Content-Type SHALL be application/prs.coverage+json.
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
### `abstract_tests[]`
|
|
475
|
+
|
|
476
|
+
Every `requirement_id` must match an existing requirement `id` — the model validator will reject the profile if not.
|
|
477
|
+
|
|
478
|
+
| Field | Type | Required | Description |
|
|
479
|
+
|---|---|---|---|
|
|
480
|
+
| `id` | `string` | yes | Must equal `requirement_id` |
|
|
481
|
+
| `requirement_id` | `string` | yes | The `id` of the requirement this test validates |
|
|
482
|
+
| `steps` | `list[string]` | yes | Ordered test steps |
|
|
483
|
+
|
|
484
|
+
```yaml
|
|
485
|
+
abstract_tests:
|
|
486
|
+
- id: position-coveragejson
|
|
487
|
+
requirement_id: position-coveragejson
|
|
488
|
+
steps:
|
|
489
|
+
- Send GET request to /collections/{id}/position?coords=POINT(lon lat).
|
|
490
|
+
- Verify the response Content-Type is application/prs.coverage+json.
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
### `pubsub`
|
|
496
|
+
|
|
497
|
+
When present, an `asyncapi.yaml` is generated.
|
|
498
|
+
|
|
499
|
+
| Field | Type | Default | Description |
|
|
500
|
+
|---|---|---|---|
|
|
501
|
+
| `broker_host` | `string` | `localhost` | Message broker hostname |
|
|
502
|
+
| `broker_port` | `integer` | `5672` | Broker port (1–65535) |
|
|
503
|
+
| `protocol` | `string` | `amqp` | One of `amqp`, `mqtt`, `kafka` |
|
|
504
|
+
| `filters` | `list` | `[]` | Subscription filters |
|
|
505
|
+
|
|
506
|
+
Each filter: `name` (required), `description` (required), `type` (one of `string`, `number`, `array`, `boolean`, default `string`).
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### `document_metadata`
|
|
511
|
+
|
|
512
|
+
Controls the Metanorma document header when compiling a PDF with `--pdf`.
|
|
513
|
+
|
|
514
|
+
| Field | Type | Required | Description |
|
|
515
|
+
|---|---|---|---|
|
|
516
|
+
| `doc_number` | `string` | yes | OGC document number e.g. `24-nwsviz` |
|
|
517
|
+
| `doc_subtype` | `string` | yes | One of `implementation`, `best-practice`, `engineering-report` |
|
|
518
|
+
| `editors` | `list[string]` | yes | Editor names |
|
|
519
|
+
| `submitting_orgs` | `list[string]` | yes | Submitting organization names |
|
|
520
|
+
| `keywords` | `list[string]` | no | Document keywords |
|
|
521
|
+
| `copyright_year` | `integer` | no | Defaults to current year |
|
|
522
|
+
| `external_id` | `string` | no | OGC external document URI |
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## OGC API - EDR Part 3 Compliance
|
|
527
|
+
|
|
528
|
+
This tool implements the requirements of OGC API - EDR Part 3: Service Profiles (draft standard):
|
|
529
|
+
|
|
530
|
+
### Key Compliance Features
|
|
531
|
+
|
|
532
|
+
1. **Profile OpenAPI Document** (REQ_publishing)
|
|
533
|
+
- Generated OpenAPI has empty `servers` array (profile is implementation-independent)
|
|
534
|
+
- Landing page schema requires `profile` link relation
|
|
535
|
+
- Profile URI advertised in `x-ogc-profile` info field
|
|
536
|
+
|
|
537
|
+
2. **Conformance Classes** (REQ_api)
|
|
538
|
+
- `/conformance` endpoint schema specifies required conformance classes
|
|
539
|
+
- Defaults to EDR Core, customizable via `required_conformance_classes`
|
|
540
|
+
|
|
541
|
+
3. **Parameter Names** (REQ_parameter-names)
|
|
542
|
+
- Validates that all parameters specify `unit` and `observedProperty`
|
|
543
|
+
- Automatically enforced during profile validation
|
|
544
|
+
|
|
545
|
+
4. **Extent Requirements** (REQ_extent)
|
|
546
|
+
- Profile-level `extent_requirements` specify minimum bounds
|
|
547
|
+
- CRS/TRS/VRS restrictions via enumerated lists or regex patterns
|
|
548
|
+
|
|
549
|
+
5. **Output Formats** (REQ_output-format)
|
|
550
|
+
- Profile-level `output_formats` with schema references
|
|
551
|
+
- Links to JSON Schema, XML Schema, or format specifications
|
|
552
|
+
|
|
553
|
+
6. **Pub/Sub** (REQ_pubsub)
|
|
554
|
+
- Automatically adds Part 2 conformance requirement when `pubsub` is present
|
|
555
|
+
- AsyncAPI document specifies channels and payloads
|
|
556
|
+
|
|
557
|
+
### Profile Types
|
|
558
|
+
|
|
559
|
+
The tool supports both:
|
|
560
|
+
- **Class 1 Profiles**: Restrictive profiles that constrain EDR Core
|
|
561
|
+
- **Class 2 Profiles**: Extended profiles that add custom requirements (e.g., processes)
|
|
562
|
+
|
|
563
|
+
Both remain compliant with EDR Core - extensions are optional, not mandatory.
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
567
|
+
## Programmatic Use
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
from oapi_profile_builder.models import ServiceProfile
|
|
571
|
+
from oapi_profile_builder.generate import generate
|
|
572
|
+
from pathlib import Path
|
|
573
|
+
|
|
574
|
+
profile = ServiceProfile.model_validate(config_dict)
|
|
575
|
+
generate(profile, Path("./output"))
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
## Repository Structure
|
|
579
|
+
|
|
580
|
+
```
|
|
581
|
+
├── src/
|
|
582
|
+
│ └── oapi_profile_builder/
|
|
583
|
+
│ ├── models.py # Authoritative Pydantic schema
|
|
584
|
+
│ ├── generate.py # Validated model → OpenAPI, AsyncAPI, AsciiDoc
|
|
585
|
+
│ ├── compile.py # PDF compilation via metanorma/metanorma Docker image
|
|
586
|
+
│ ├── cite.py # OGC CITE test suite orchestration
|
|
587
|
+
│ └── cli.py # CLI entry point
|
|
588
|
+
├── examples/
|
|
589
|
+
│ ├── water_gauge.yaml # Minimal example profile config
|
|
590
|
+
│ └── nwsviz_profile.yaml # Full NWSViz profile: 13 collections, 3 processes, PDF metadata
|
|
591
|
+
├── profile.schema.json # Machine-readable JSON Schema for profile configs
|
|
592
|
+
└── pyproject.toml
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
## Standards
|
|
596
|
+
|
|
597
|
+
- OGC API - EDR Part 1: Core
|
|
598
|
+
- OGC API - EDR Part 2: PubSub
|
|
599
|
+
- OGC API - EDR Part 3: Service Profiles (draft)
|
|
600
|
+
- OGC API - Processes Part 1
|
|
601
|
+
- OpenAPI 3.0 / AsyncAPI 3.0
|
|
602
|
+
- Metanorma/AsciiDoc documentation format
|
|
603
|
+
|
|
604
|
+
## License
|
|
605
|
+
|
|
606
|
+
MIT — See [LICENSE](LICENSE) for details.
|
|
607
|
+
|
|
608
|
+
## Contact
|
|
609
|
+
|
|
610
|
+
- **Author**: Shane Mill (NOAA/NWS/MDL)
|
|
611
|
+
- **Email**: shane.mill@noaa.gov
|
|
612
|
+
- **Issues**: https://github.com/ShaneMill1/OGC-API-Service-Profile-Builder/issues
|