oapi-profile-builder 3.4.0__tar.gz → 3.5.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-3.4.0/src/oapi_profile_builder.egg-info → oapi_profile_builder-3.5.0}/PKG-INFO +96 -2
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/README.md +95 -1
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/pyproject.toml +1 -1
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/generate.py +290 -37
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/models.py +305 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0/src/oapi_profile_builder.egg-info}/PKG-INFO +96 -2
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/LICENSE +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/setup.cfg +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/__init__.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/cite.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/cite_features.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/cli.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/compile.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/cover.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder/server_validation.py +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder.egg-info/SOURCES.txt +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder.egg-info/dependency_links.txt +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder.egg-info/entry_points.txt +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder.egg-info/requires.txt +0 -0
- {oapi_profile_builder-3.4.0 → oapi_profile_builder-3.5.0}/src/oapi_profile_builder.egg-info/top_level.txt +0 -0
{oapi_profile_builder-3.4.0/src/oapi_profile_builder.egg-info → oapi_profile_builder-3.5.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oapi-profile-builder
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: Authoritative tooling for creating OGC API Service Profiles (EDR, Features)
|
|
5
5
|
Author-email: Shane Mill <shane.mill@noaa.gov>
|
|
6
6
|
License: Apache License
|
|
@@ -239,15 +239,21 @@ Everything about the document — cover, title-page metadata, legal page, footer
|
|
|
239
239
|
| PDF colours (titles, tables, cover, backgrounds) | `document_metadata.colors` | `:presentation-metadata-color-*:` |
|
|
240
240
|
| Page-ii legal text (copyright / license / notice) | `document_metadata.boilerplate` | `:boilerplate-authority:` |
|
|
241
241
|
| Footer organisation name | `document_metadata.copyright_holder` | `:copyright-holder:` |
|
|
242
|
+
| Cover layout (logo size/position, tagline/title size, bold edition) | `document_metadata.cover.{logo_width, logo_y, tagline_font_size, title_font_size, bold_edition}` | Generated cover image |
|
|
243
|
+
| Cover date | `document_metadata.doc_pub_date` | Long-format date on the generated cover + `:published-date:` |
|
|
242
244
|
| Remove the OGC logo from the legal page | `document_metadata.suppress_flavor_logo` | targeted `:pdf-stylesheet-override:` |
|
|
243
245
|
| Remove OGC design (crossing lines, circled numbers, rules, navy divider pages) | `document_metadata.suppress_design_elements` (or the individual `suppress_crossing_lines` / `plain_section_numbers` / `suppress_title_underlines`) | `:pdf-stylesheet-override:` + colour attributes |
|
|
246
|
+
| Remove the standalone section-divider pages | `document_metadata.suppress_section_divider_pages` | `:pdf-stylesheet-override:` |
|
|
247
|
+
| Inline section headings (`1 Scope` in one line, no circle) | `document_metadata.inline_section_headers` | `:pdf-stylesheet-override:` |
|
|
248
|
+
| Flatten reference hanging indent (title under authors) | `document_metadata.suppress_bibliography_indent` | `:pdf-stylesheet-override:` |
|
|
244
249
|
| Every-page DRAFT-style watermark (over content) | `document_metadata.page_watermark` | `:pdf-stylesheet-override:` (footer overlay) |
|
|
245
250
|
| Requirement / conformance identifier namespace | `spec_uri_base` | derives `req_uri` / `conf_uri` |
|
|
246
251
|
| Submitter table, notice paragraph, normative refs, extra terms | `document_metadata.{submitters, notice, normative_references, terms}` | Metanorma attributes / sections |
|
|
252
|
+
| Features `/items` paging (`limit` parameter) | `paging.{enabled, default_limit, max_limit}` | OpenAPI query parameter |
|
|
247
253
|
|
|
248
254
|
Custom branding requires Pillow for the cover image: `pip install 'oapi-profile-builder[pdf]'`. Field-by-field detail is in the [`document_metadata`](#document_metadata) reference below; [`examples/nwp_radar.yaml`](examples/nwp_radar.yaml) is a complete DGIWG-branded example. Omit all of these fields and the output keeps the standard OGC house style.
|
|
249
255
|
|
|
250
|
-
> The `suppress_flavor_logo`, `suppress_design_elements`/`suppress_*`, and `page_watermark` overrides reach into the OGC Metanorma flavor's XSL templates (e.g. `insertLogoPreface`, `insertCrossingLines`, `insertSectionNumInCircle`, `insertFooter`) and are coupled to that flavor. Everything else uses documented Metanorma attributes. mn2pdf merges our same-named templates over the flavor's at equal precedence (via `merge_override.xsl`), which is what makes these work; a future metanorma-ogc release could require refreshing the template names. For long-term SDO adoption, a dedicated Metanorma "taste"/flavor is the most durable path.
|
|
256
|
+
> The `suppress_flavor_logo`, `suppress_design_elements`/`suppress_*`, `suppress_section_divider_pages`, `inline_section_headers`, `suppress_bibliography_indent`, and `page_watermark` overrides reach into the OGC Metanorma flavor's XSL templates (e.g. `insertLogoPreface`, `insertCrossingLines`, `insertSectionNumInCircle`, `insertFooter`, the `sections` mode, `fmt-title`, and `bibitem-normative-style`) and are coupled to that flavor. Everything else uses documented Metanorma attributes. mn2pdf merges our same-named templates over the flavor's at equal precedence (via `merge_override.xsl`), which is what makes these work; a future metanorma-ogc release could require refreshing the template names. For long-term SDO adoption, a dedicated Metanorma "taste"/flavor is the most durable path.
|
|
251
257
|
|
|
252
258
|
---
|
|
253
259
|
|
|
@@ -336,11 +342,19 @@ abstract_tests: []
|
|
|
336
342
|
| `spec_uri_base` | string | no | Base URI for the requirements/conformance class identifiers. Defaults to the OGC EDR Part 3 namespace; override to publish under another SDO namespace (e.g. DGIWG) |
|
|
337
343
|
| `parameter_name_pattern` | string | no | Regex all `parameter_names` keys must match |
|
|
338
344
|
| `parameter_schema` | object | no | JSON Schema for parameter objects — replaces the default schema in the generated OpenAPI (see below) |
|
|
345
|
+
| `collection_title_max_length` | int | no | When set, every collection title must be present and within this many characters (MetOcean `/req/core/collection_title`) |
|
|
346
|
+
| `require_license_link` | bool | no | When `true`, every collection must declare a `rel='license'` link (MetOcean `/req/core/collection_license`). Defaults to `false` |
|
|
347
|
+
| `license_link_type` | string | no | Expected media type of the `rel='license'` link when `require_license_link` is set. Defaults to `text/html`; set to null to accept any type |
|
|
348
|
+
| `required_data_queries` | list | no | Data-query types every collection must define (e.g. `[locations, area, radius]`) — enforces the mandatory data-query sets |
|
|
349
|
+
| `radius_within_units_required` | list | no | Unit tokens each radius query's `within_units` must contain (e.g. `[m]`) (MetOcean `/req/core/collection_radius_data_query`) |
|
|
350
|
+
| `locations_feature_required_properties` | list | no | Feature properties (e.g. `[name]`) marked required in the generated `/locations` GeoJSON response schema, in addition to the always-required string `id` |
|
|
351
|
+
| `conformance_class_requirements` | object | no | Map of conformance-class short name → constraints (`required_data_queries`, `radius_within_units_required`) applied only to collections that declare the class. Lets one profile document model several EDR Part 3 requirements classes (see below) |
|
|
339
352
|
| `processes` | list | no | OGC API Processes to expose in the OpenAPI |
|
|
340
353
|
| `requirements` | list | no | Normative requirements for the AsciiDoc/PDF |
|
|
341
354
|
| `abstract_tests` | list | no | Conformance tests — each must reference a valid requirement `id` |
|
|
342
355
|
| `pubsub` | object | no | OGC API - EDR Part 2 PubSub config — generates `asyncapi.yaml` |
|
|
343
356
|
| `collection_examples` | object | no | `{collectionId: {instanceId: "..."}}` — used by `validate-server` |
|
|
357
|
+
| `paging` | object | no | Features `/items` paging — adds a validated `limit` query parameter to the generated OpenAPI (see below) |
|
|
344
358
|
| `document_metadata` | object | no | Metanorma PDF header — doc number/type/subtype, status, editors, submitters, dates, notice, normative references (see below) |
|
|
345
359
|
|
|
346
360
|
---
|
|
@@ -374,6 +388,8 @@ Uses the [edr-pydantic](https://github.com/KNMI/edr-pydantic) `Collection` model
|
|
|
374
388
|
| `output_formats` | no | Format names this collection supports (e.g. `[CoverageJSON, GeoJSON]`) |
|
|
375
389
|
| `data_queries` | no | EDR query types: `position`, `area`, `radius`, `cube`, `trajectory`, `corridor`, `locations`, `items`, `instances` |
|
|
376
390
|
| `parameter_names` | no | Map of parameter id → Parameter object. All parameters must have `unit` and `observedProperty` |
|
|
391
|
+
| `conformance_classes` | no | Profile conformance-class short names this collection implements (e.g. `[core, insitu-observations]`). Selects which `conformance_class_requirements` are enforced; surfaced as `x-conformance-classes` in the OpenAPI |
|
|
392
|
+
| `parameter_schema` | no | Per-collection JSON Schema for parameter objects, overriding the profile-level `parameter_schema` for this collection only (precedence: collection → profile → default) |
|
|
377
393
|
|
|
378
394
|
#### `data_queries` example
|
|
379
395
|
|
|
@@ -506,6 +522,38 @@ extent_requirements:
|
|
|
506
522
|
|
|
507
523
|
---
|
|
508
524
|
|
|
525
|
+
### Multiple conformance classes in one profile
|
|
526
|
+
|
|
527
|
+
OGC API - EDR Part 3 profiles are modular: a single profile document can define several requirements/conformance classes, and different collections in the same service may implement different classes. The MetOcean EDR Profile is a good example — Core applies everywhere, but only in-situ collections must offer `locations`/`area`/`radius` while NWP collections must offer `position`/`cube`.
|
|
528
|
+
|
|
529
|
+
Model this with `conformance_class_requirements` (profile level) plus `conformance_classes` (per collection):
|
|
530
|
+
|
|
531
|
+
```yaml
|
|
532
|
+
# Core-level rules apply to every collection:
|
|
533
|
+
collection_title_max_length: 50
|
|
534
|
+
require_license_link: true
|
|
535
|
+
|
|
536
|
+
# Class-scoped rules apply only where a collection opts in:
|
|
537
|
+
conformance_class_requirements:
|
|
538
|
+
insitu-observations:
|
|
539
|
+
required_data_queries: [locations, area, radius]
|
|
540
|
+
radius_within_units_required: [m]
|
|
541
|
+
nwp:
|
|
542
|
+
required_data_queries: [position, cube]
|
|
543
|
+
|
|
544
|
+
collections:
|
|
545
|
+
- id: insitu-observations
|
|
546
|
+
conformance_classes: [core, insitu-observations] # must have locations/area/radius
|
|
547
|
+
# ...
|
|
548
|
+
- id: nwp-forecast
|
|
549
|
+
conformance_classes: [core, nwp] # must have position/cube
|
|
550
|
+
# ...
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
The flat `required_data_queries` / `radius_within_units_required` fields still apply to *every* collection (the Core-applies-to-all shorthand); class-scoped rules are additive. See `examples/metocean_profile.yaml` for a full worked profile spanning all four MetOcean classes.
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
509
557
|
### `output_formats`
|
|
510
558
|
|
|
511
559
|
Maps format names (referenced by `collections[].output_formats` and `data_queries.*.variables.output_formats`) to a media type and, optionally, a schema reference. The `schema_ref` flows into the generated OpenAPI response `content` for that format — use it to point a format at a specific schema (e.g. a DGIWG-published schema for GeoTIFF or CoverageJSON) instead of the tool's built-in default.
|
|
@@ -624,6 +672,21 @@ Generates: `/processes/compute-difference`, `/processes/compute-difference/execu
|
|
|
624
672
|
|
|
625
673
|
---
|
|
626
674
|
|
|
675
|
+
### `paging`
|
|
676
|
+
|
|
677
|
+
Controls Features `/items` paging in the generated OpenAPI. When enabled (the default), a validated `limit` query parameter is added to every `/items` endpoint (collection-level and instance-level).
|
|
678
|
+
|
|
679
|
+
```yaml
|
|
680
|
+
paging:
|
|
681
|
+
enabled: true # default true; set false to omit the limit parameter
|
|
682
|
+
default_limit: 10 # OpenAPI schema default for limit (default 10)
|
|
683
|
+
max_limit: 100 # OpenAPI schema maximum for limit (default 10000)
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
The emitted parameter is `limit` (`in: query`, `type: integer`, `minimum: 1`, `maximum: <max_limit>`, `default: <default_limit>`).
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
627
690
|
### `pubsub`
|
|
628
691
|
|
|
629
692
|
When present, generates `asyncapi.yaml` alongside `openapi.yaml`.
|
|
@@ -669,6 +732,8 @@ document_metadata:
|
|
|
669
732
|
submission_date: "2026-05-01" # → :received-date:
|
|
670
733
|
approval_date: "2026-06-15" # → :issued-date:
|
|
671
734
|
publication_date: "2026-07-01" # → :published-date:
|
|
735
|
+
doc_pub_date: "2026-07-16" # optional; overrides publication_date for the cover
|
|
736
|
+
# (long-format "16 July 2026") and :published-date:
|
|
672
737
|
# Custom notice paragraph rendered in the front matter. Note: the OGC cover-page
|
|
673
738
|
# legal notice itself is generated by Metanorma from doc_type/status.
|
|
674
739
|
notice: >
|
|
@@ -707,6 +772,12 @@ document_metadata:
|
|
|
707
772
|
font_bold: "Source Sans Pro" # optional bold face; derived from font_regular when unset
|
|
708
773
|
font_italic: "Source Sans Pro" # optional italic face for the tagline
|
|
709
774
|
watermark: "DRAFT" # optional diagonal watermark stamped on the cover
|
|
775
|
+
# --- cover layout (all optional) ---
|
|
776
|
+
logo_width: 200 # target logo width in px (default 420)
|
|
777
|
+
logo_y: 100 # logo vertical offset from top in px (default 180)
|
|
778
|
+
tagline_font_size: 20 # tagline point size (default 30)
|
|
779
|
+
title_font_size: 40 # title point size (default 54)
|
|
780
|
+
bold_edition: true # render the "Edition X" line in bold (default false)
|
|
710
781
|
colors:
|
|
711
782
|
text: "#000000" # body text
|
|
712
783
|
cover_text: "#1F3864" # cover text / section numbers / ToC
|
|
@@ -763,6 +834,23 @@ With `cover` + `colors` + `copyright_holder` + `boilerplate` + `suppress_flavor_
|
|
|
763
834
|
|
|
764
835
|
> These design-element overrides (and the `page_watermark` footer overlay) reach into the OGC Metanorma flavor's XSL template names and are coupled to that flavor; a future metanorma-ogc release could require refreshing them.
|
|
765
836
|
|
|
837
|
+
#### Structural layout changes (divider pages, inline headers, references)
|
|
838
|
+
|
|
839
|
+
`suppress_design_elements` only changes *decorative* styling — it keeps the document's structure (standalone section-divider pages, the standard heading layout, and the reference hanging indent) intact. The following are **independent, opt-in** structural changes, so the default OGC output is unaffected unless you set them:
|
|
840
|
+
|
|
841
|
+
- **`suppress_section_divider_pages: true`** — removes the standalone full-page section dividers, so each section's content follows its heading directly.
|
|
842
|
+
- **`inline_section_headers: true`** — renders Level 1/2 headings inline with the title (e.g. `1 Scope`, `i Abstract`) rather than the OGC circled-number layout.
|
|
843
|
+
- **`suppress_bibliography_indent: true`** — flattens both the Normative References and the Bibliography so each entry is a single flush paragraph, removing the hanging indent that placed the title under the authors.
|
|
844
|
+
|
|
845
|
+
```yaml
|
|
846
|
+
document_metadata:
|
|
847
|
+
suppress_section_divider_pages: true
|
|
848
|
+
inline_section_headers: true
|
|
849
|
+
suppress_bibliography_indent: true
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
Additionally, when `copyright_holder` is set to a non-OGC organisation, the flavor's auto-generated "Submitting Organizations" sentence ("…submitted this Document to the Open Geospatial Consortium (OGC)") is rebranded to name that organisation instead, so no residual OGC text remains in the preface.
|
|
853
|
+
|
|
766
854
|
#### Extending Terms and Definitions
|
|
767
855
|
|
|
768
856
|
Add profile-specific terms (e.g. EDR Part 3 or Pub/Sub terms) appended after the base terms in the Terms and Definitions section:
|
|
@@ -851,6 +939,12 @@ The tool enforces these rules at build time. Violations produce clear error mess
|
|
|
851
939
|
| Parameters need `unit` + `observedProperty` | Required by OGC API - EDR Part 3 |
|
|
852
940
|
| `parameter_name_pattern` enforced | All `parameter_names` keys must match if set |
|
|
853
941
|
| `collection_id_pattern` enforced | All collection IDs must match if set |
|
|
942
|
+
| `collection_title_max_length` enforced | If set, every collection title must be present and within the limit |
|
|
943
|
+
| `require_license_link` enforced | If set, every collection must have a `rel='license'` link (of `license_link_type` when specified) |
|
|
944
|
+
| `required_data_queries` enforced | If set, every collection with `data_queries` must define each listed query type |
|
|
945
|
+
| `radius_within_units_required` enforced | If set, each radius query's `within_units` must contain every listed unit token |
|
|
946
|
+
| `conformance_class_requirements` enforced | Class-scoped `required_data_queries` / `radius_within_units_required` applied to collections whose `conformance_classes` include the class key |
|
|
947
|
+
| `conformance_classes` references known class | When `conformance_class_requirements` is set, a collection's `conformance_classes` may only use `core` or a defined class key (catches typos) |
|
|
854
948
|
| Abstract test IDs match requirements | `requirement_id` must reference an existing requirement |
|
|
855
949
|
| Requirement IDs | Must match `^[a-z0-9][a-z0-9\-]*$`, no trailing hyphen |
|
|
856
950
|
|
|
@@ -192,15 +192,21 @@ Everything about the document — cover, title-page metadata, legal page, footer
|
|
|
192
192
|
| PDF colours (titles, tables, cover, backgrounds) | `document_metadata.colors` | `:presentation-metadata-color-*:` |
|
|
193
193
|
| Page-ii legal text (copyright / license / notice) | `document_metadata.boilerplate` | `:boilerplate-authority:` |
|
|
194
194
|
| Footer organisation name | `document_metadata.copyright_holder` | `:copyright-holder:` |
|
|
195
|
+
| Cover layout (logo size/position, tagline/title size, bold edition) | `document_metadata.cover.{logo_width, logo_y, tagline_font_size, title_font_size, bold_edition}` | Generated cover image |
|
|
196
|
+
| Cover date | `document_metadata.doc_pub_date` | Long-format date on the generated cover + `:published-date:` |
|
|
195
197
|
| Remove the OGC logo from the legal page | `document_metadata.suppress_flavor_logo` | targeted `:pdf-stylesheet-override:` |
|
|
196
198
|
| Remove OGC design (crossing lines, circled numbers, rules, navy divider pages) | `document_metadata.suppress_design_elements` (or the individual `suppress_crossing_lines` / `plain_section_numbers` / `suppress_title_underlines`) | `:pdf-stylesheet-override:` + colour attributes |
|
|
199
|
+
| Remove the standalone section-divider pages | `document_metadata.suppress_section_divider_pages` | `:pdf-stylesheet-override:` |
|
|
200
|
+
| Inline section headings (`1 Scope` in one line, no circle) | `document_metadata.inline_section_headers` | `:pdf-stylesheet-override:` |
|
|
201
|
+
| Flatten reference hanging indent (title under authors) | `document_metadata.suppress_bibliography_indent` | `:pdf-stylesheet-override:` |
|
|
197
202
|
| Every-page DRAFT-style watermark (over content) | `document_metadata.page_watermark` | `:pdf-stylesheet-override:` (footer overlay) |
|
|
198
203
|
| Requirement / conformance identifier namespace | `spec_uri_base` | derives `req_uri` / `conf_uri` |
|
|
199
204
|
| Submitter table, notice paragraph, normative refs, extra terms | `document_metadata.{submitters, notice, normative_references, terms}` | Metanorma attributes / sections |
|
|
205
|
+
| Features `/items` paging (`limit` parameter) | `paging.{enabled, default_limit, max_limit}` | OpenAPI query parameter |
|
|
200
206
|
|
|
201
207
|
Custom branding requires Pillow for the cover image: `pip install 'oapi-profile-builder[pdf]'`. Field-by-field detail is in the [`document_metadata`](#document_metadata) reference below; [`examples/nwp_radar.yaml`](examples/nwp_radar.yaml) is a complete DGIWG-branded example. Omit all of these fields and the output keeps the standard OGC house style.
|
|
202
208
|
|
|
203
|
-
> The `suppress_flavor_logo`, `suppress_design_elements`/`suppress_*`, and `page_watermark` overrides reach into the OGC Metanorma flavor's XSL templates (e.g. `insertLogoPreface`, `insertCrossingLines`, `insertSectionNumInCircle`, `insertFooter`) and are coupled to that flavor. Everything else uses documented Metanorma attributes. mn2pdf merges our same-named templates over the flavor's at equal precedence (via `merge_override.xsl`), which is what makes these work; a future metanorma-ogc release could require refreshing the template names. For long-term SDO adoption, a dedicated Metanorma "taste"/flavor is the most durable path.
|
|
209
|
+
> The `suppress_flavor_logo`, `suppress_design_elements`/`suppress_*`, `suppress_section_divider_pages`, `inline_section_headers`, `suppress_bibliography_indent`, and `page_watermark` overrides reach into the OGC Metanorma flavor's XSL templates (e.g. `insertLogoPreface`, `insertCrossingLines`, `insertSectionNumInCircle`, `insertFooter`, the `sections` mode, `fmt-title`, and `bibitem-normative-style`) and are coupled to that flavor. Everything else uses documented Metanorma attributes. mn2pdf merges our same-named templates over the flavor's at equal precedence (via `merge_override.xsl`), which is what makes these work; a future metanorma-ogc release could require refreshing the template names. For long-term SDO adoption, a dedicated Metanorma "taste"/flavor is the most durable path.
|
|
204
210
|
|
|
205
211
|
---
|
|
206
212
|
|
|
@@ -289,11 +295,19 @@ abstract_tests: []
|
|
|
289
295
|
| `spec_uri_base` | string | no | Base URI for the requirements/conformance class identifiers. Defaults to the OGC EDR Part 3 namespace; override to publish under another SDO namespace (e.g. DGIWG) |
|
|
290
296
|
| `parameter_name_pattern` | string | no | Regex all `parameter_names` keys must match |
|
|
291
297
|
| `parameter_schema` | object | no | JSON Schema for parameter objects — replaces the default schema in the generated OpenAPI (see below) |
|
|
298
|
+
| `collection_title_max_length` | int | no | When set, every collection title must be present and within this many characters (MetOcean `/req/core/collection_title`) |
|
|
299
|
+
| `require_license_link` | bool | no | When `true`, every collection must declare a `rel='license'` link (MetOcean `/req/core/collection_license`). Defaults to `false` |
|
|
300
|
+
| `license_link_type` | string | no | Expected media type of the `rel='license'` link when `require_license_link` is set. Defaults to `text/html`; set to null to accept any type |
|
|
301
|
+
| `required_data_queries` | list | no | Data-query types every collection must define (e.g. `[locations, area, radius]`) — enforces the mandatory data-query sets |
|
|
302
|
+
| `radius_within_units_required` | list | no | Unit tokens each radius query's `within_units` must contain (e.g. `[m]`) (MetOcean `/req/core/collection_radius_data_query`) |
|
|
303
|
+
| `locations_feature_required_properties` | list | no | Feature properties (e.g. `[name]`) marked required in the generated `/locations` GeoJSON response schema, in addition to the always-required string `id` |
|
|
304
|
+
| `conformance_class_requirements` | object | no | Map of conformance-class short name → constraints (`required_data_queries`, `radius_within_units_required`) applied only to collections that declare the class. Lets one profile document model several EDR Part 3 requirements classes (see below) |
|
|
292
305
|
| `processes` | list | no | OGC API Processes to expose in the OpenAPI |
|
|
293
306
|
| `requirements` | list | no | Normative requirements for the AsciiDoc/PDF |
|
|
294
307
|
| `abstract_tests` | list | no | Conformance tests — each must reference a valid requirement `id` |
|
|
295
308
|
| `pubsub` | object | no | OGC API - EDR Part 2 PubSub config — generates `asyncapi.yaml` |
|
|
296
309
|
| `collection_examples` | object | no | `{collectionId: {instanceId: "..."}}` — used by `validate-server` |
|
|
310
|
+
| `paging` | object | no | Features `/items` paging — adds a validated `limit` query parameter to the generated OpenAPI (see below) |
|
|
297
311
|
| `document_metadata` | object | no | Metanorma PDF header — doc number/type/subtype, status, editors, submitters, dates, notice, normative references (see below) |
|
|
298
312
|
|
|
299
313
|
---
|
|
@@ -327,6 +341,8 @@ Uses the [edr-pydantic](https://github.com/KNMI/edr-pydantic) `Collection` model
|
|
|
327
341
|
| `output_formats` | no | Format names this collection supports (e.g. `[CoverageJSON, GeoJSON]`) |
|
|
328
342
|
| `data_queries` | no | EDR query types: `position`, `area`, `radius`, `cube`, `trajectory`, `corridor`, `locations`, `items`, `instances` |
|
|
329
343
|
| `parameter_names` | no | Map of parameter id → Parameter object. All parameters must have `unit` and `observedProperty` |
|
|
344
|
+
| `conformance_classes` | no | Profile conformance-class short names this collection implements (e.g. `[core, insitu-observations]`). Selects which `conformance_class_requirements` are enforced; surfaced as `x-conformance-classes` in the OpenAPI |
|
|
345
|
+
| `parameter_schema` | no | Per-collection JSON Schema for parameter objects, overriding the profile-level `parameter_schema` for this collection only (precedence: collection → profile → default) |
|
|
330
346
|
|
|
331
347
|
#### `data_queries` example
|
|
332
348
|
|
|
@@ -459,6 +475,38 @@ extent_requirements:
|
|
|
459
475
|
|
|
460
476
|
---
|
|
461
477
|
|
|
478
|
+
### Multiple conformance classes in one profile
|
|
479
|
+
|
|
480
|
+
OGC API - EDR Part 3 profiles are modular: a single profile document can define several requirements/conformance classes, and different collections in the same service may implement different classes. The MetOcean EDR Profile is a good example — Core applies everywhere, but only in-situ collections must offer `locations`/`area`/`radius` while NWP collections must offer `position`/`cube`.
|
|
481
|
+
|
|
482
|
+
Model this with `conformance_class_requirements` (profile level) plus `conformance_classes` (per collection):
|
|
483
|
+
|
|
484
|
+
```yaml
|
|
485
|
+
# Core-level rules apply to every collection:
|
|
486
|
+
collection_title_max_length: 50
|
|
487
|
+
require_license_link: true
|
|
488
|
+
|
|
489
|
+
# Class-scoped rules apply only where a collection opts in:
|
|
490
|
+
conformance_class_requirements:
|
|
491
|
+
insitu-observations:
|
|
492
|
+
required_data_queries: [locations, area, radius]
|
|
493
|
+
radius_within_units_required: [m]
|
|
494
|
+
nwp:
|
|
495
|
+
required_data_queries: [position, cube]
|
|
496
|
+
|
|
497
|
+
collections:
|
|
498
|
+
- id: insitu-observations
|
|
499
|
+
conformance_classes: [core, insitu-observations] # must have locations/area/radius
|
|
500
|
+
# ...
|
|
501
|
+
- id: nwp-forecast
|
|
502
|
+
conformance_classes: [core, nwp] # must have position/cube
|
|
503
|
+
# ...
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
The flat `required_data_queries` / `radius_within_units_required` fields still apply to *every* collection (the Core-applies-to-all shorthand); class-scoped rules are additive. See `examples/metocean_profile.yaml` for a full worked profile spanning all four MetOcean classes.
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
462
510
|
### `output_formats`
|
|
463
511
|
|
|
464
512
|
Maps format names (referenced by `collections[].output_formats` and `data_queries.*.variables.output_formats`) to a media type and, optionally, a schema reference. The `schema_ref` flows into the generated OpenAPI response `content` for that format — use it to point a format at a specific schema (e.g. a DGIWG-published schema for GeoTIFF or CoverageJSON) instead of the tool's built-in default.
|
|
@@ -577,6 +625,21 @@ Generates: `/processes/compute-difference`, `/processes/compute-difference/execu
|
|
|
577
625
|
|
|
578
626
|
---
|
|
579
627
|
|
|
628
|
+
### `paging`
|
|
629
|
+
|
|
630
|
+
Controls Features `/items` paging in the generated OpenAPI. When enabled (the default), a validated `limit` query parameter is added to every `/items` endpoint (collection-level and instance-level).
|
|
631
|
+
|
|
632
|
+
```yaml
|
|
633
|
+
paging:
|
|
634
|
+
enabled: true # default true; set false to omit the limit parameter
|
|
635
|
+
default_limit: 10 # OpenAPI schema default for limit (default 10)
|
|
636
|
+
max_limit: 100 # OpenAPI schema maximum for limit (default 10000)
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
The emitted parameter is `limit` (`in: query`, `type: integer`, `minimum: 1`, `maximum: <max_limit>`, `default: <default_limit>`).
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
580
643
|
### `pubsub`
|
|
581
644
|
|
|
582
645
|
When present, generates `asyncapi.yaml` alongside `openapi.yaml`.
|
|
@@ -622,6 +685,8 @@ document_metadata:
|
|
|
622
685
|
submission_date: "2026-05-01" # → :received-date:
|
|
623
686
|
approval_date: "2026-06-15" # → :issued-date:
|
|
624
687
|
publication_date: "2026-07-01" # → :published-date:
|
|
688
|
+
doc_pub_date: "2026-07-16" # optional; overrides publication_date for the cover
|
|
689
|
+
# (long-format "16 July 2026") and :published-date:
|
|
625
690
|
# Custom notice paragraph rendered in the front matter. Note: the OGC cover-page
|
|
626
691
|
# legal notice itself is generated by Metanorma from doc_type/status.
|
|
627
692
|
notice: >
|
|
@@ -660,6 +725,12 @@ document_metadata:
|
|
|
660
725
|
font_bold: "Source Sans Pro" # optional bold face; derived from font_regular when unset
|
|
661
726
|
font_italic: "Source Sans Pro" # optional italic face for the tagline
|
|
662
727
|
watermark: "DRAFT" # optional diagonal watermark stamped on the cover
|
|
728
|
+
# --- cover layout (all optional) ---
|
|
729
|
+
logo_width: 200 # target logo width in px (default 420)
|
|
730
|
+
logo_y: 100 # logo vertical offset from top in px (default 180)
|
|
731
|
+
tagline_font_size: 20 # tagline point size (default 30)
|
|
732
|
+
title_font_size: 40 # title point size (default 54)
|
|
733
|
+
bold_edition: true # render the "Edition X" line in bold (default false)
|
|
663
734
|
colors:
|
|
664
735
|
text: "#000000" # body text
|
|
665
736
|
cover_text: "#1F3864" # cover text / section numbers / ToC
|
|
@@ -716,6 +787,23 @@ With `cover` + `colors` + `copyright_holder` + `boilerplate` + `suppress_flavor_
|
|
|
716
787
|
|
|
717
788
|
> These design-element overrides (and the `page_watermark` footer overlay) reach into the OGC Metanorma flavor's XSL template names and are coupled to that flavor; a future metanorma-ogc release could require refreshing them.
|
|
718
789
|
|
|
790
|
+
#### Structural layout changes (divider pages, inline headers, references)
|
|
791
|
+
|
|
792
|
+
`suppress_design_elements` only changes *decorative* styling — it keeps the document's structure (standalone section-divider pages, the standard heading layout, and the reference hanging indent) intact. The following are **independent, opt-in** structural changes, so the default OGC output is unaffected unless you set them:
|
|
793
|
+
|
|
794
|
+
- **`suppress_section_divider_pages: true`** — removes the standalone full-page section dividers, so each section's content follows its heading directly.
|
|
795
|
+
- **`inline_section_headers: true`** — renders Level 1/2 headings inline with the title (e.g. `1 Scope`, `i Abstract`) rather than the OGC circled-number layout.
|
|
796
|
+
- **`suppress_bibliography_indent: true`** — flattens both the Normative References and the Bibliography so each entry is a single flush paragraph, removing the hanging indent that placed the title under the authors.
|
|
797
|
+
|
|
798
|
+
```yaml
|
|
799
|
+
document_metadata:
|
|
800
|
+
suppress_section_divider_pages: true
|
|
801
|
+
inline_section_headers: true
|
|
802
|
+
suppress_bibliography_indent: true
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
Additionally, when `copyright_holder` is set to a non-OGC organisation, the flavor's auto-generated "Submitting Organizations" sentence ("…submitted this Document to the Open Geospatial Consortium (OGC)") is rebranded to name that organisation instead, so no residual OGC text remains in the preface.
|
|
806
|
+
|
|
719
807
|
#### Extending Terms and Definitions
|
|
720
808
|
|
|
721
809
|
Add profile-specific terms (e.g. EDR Part 3 or Pub/Sub terms) appended after the base terms in the Terms and Definitions section:
|
|
@@ -804,6 +892,12 @@ The tool enforces these rules at build time. Violations produce clear error mess
|
|
|
804
892
|
| Parameters need `unit` + `observedProperty` | Required by OGC API - EDR Part 3 |
|
|
805
893
|
| `parameter_name_pattern` enforced | All `parameter_names` keys must match if set |
|
|
806
894
|
| `collection_id_pattern` enforced | All collection IDs must match if set |
|
|
895
|
+
| `collection_title_max_length` enforced | If set, every collection title must be present and within the limit |
|
|
896
|
+
| `require_license_link` enforced | If set, every collection must have a `rel='license'` link (of `license_link_type` when specified) |
|
|
897
|
+
| `required_data_queries` enforced | If set, every collection with `data_queries` must define each listed query type |
|
|
898
|
+
| `radius_within_units_required` enforced | If set, each radius query's `within_units` must contain every listed unit token |
|
|
899
|
+
| `conformance_class_requirements` enforced | Class-scoped `required_data_queries` / `radius_within_units_required` applied to collections whose `conformance_classes` include the class key |
|
|
900
|
+
| `conformance_classes` references known class | When `conformance_class_requirements` is set, a collection's `conformance_classes` may only use `core` or a defined class key (catches typos) |
|
|
807
901
|
| Abstract test IDs match requirements | `requirement_id` must reference an existing requirement |
|
|
808
902
|
| Requirement IDs | Must match `^[a-z0-9][a-z0-9\-]*$`, no trailing hyphen |
|
|
809
903
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "oapi-profile-builder"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.5.0"
|
|
8
8
|
description = "Authoritative tooling for creating OGC API Service Profiles (EDR, Features)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|