oapi-profile-builder 2.3.0__tar.gz → 2.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.
Files changed (19) hide show
  1. {oapi_profile_builder-2.3.0/src/oapi_profile_builder.egg-info → oapi_profile_builder-2.5.0}/PKG-INFO +8 -1
  2. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/README.md +7 -0
  3. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/pyproject.toml +1 -1
  4. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/generate.py +36 -18
  5. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/models.py +38 -9
  6. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0/src/oapi_profile_builder.egg-info}/PKG-INFO +8 -1
  7. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/LICENSE +0 -0
  8. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/setup.cfg +0 -0
  9. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/__init__.py +0 -0
  10. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/cite.py +0 -0
  11. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/cite_features.py +0 -0
  12. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/cli.py +0 -0
  13. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/compile.py +0 -0
  14. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder/server_validation.py +0 -0
  15. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder.egg-info/SOURCES.txt +0 -0
  16. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder.egg-info/dependency_links.txt +0 -0
  17. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder.egg-info/entry_points.txt +0 -0
  18. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder.egg-info/requires.txt +0 -0
  19. {oapi_profile_builder-2.3.0 → oapi_profile_builder-2.5.0}/src/oapi_profile_builder.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oapi-profile-builder
3
- Version: 2.3.0
3
+ Version: 2.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
@@ -229,6 +229,10 @@ A profile config is a YAML file. The full JSON Schema is at [`profile.schema.jso
229
229
  name: my_profile # lowercase, a-z 0-9 _ only
230
230
  title: My EDR Profile
231
231
  version: "1.0"
232
+ description: Brief description of what this service profile provides.
233
+ keywords:
234
+ - my-parameter
235
+ - my-domain
232
236
 
233
237
  required_conformance_classes:
234
238
  - "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/core"
@@ -269,7 +273,10 @@ collections:
269
273
  | `name` | string | yes | Lowercase `a-z 0-9 _`. Drives OGC URIs and OpenAPI `operationId`s |
270
274
  | `title` | string | yes | Human-readable profile title |
271
275
  | `version` | string | no | Defaults to `"1.0"` |
276
+ | `description` | string | no | Human-readable description of the service profile. Surfaces in the OpenAPI `info.description` and the landing page response schema |
277
+ | `keywords` | list | no | Service-level keywords (e.g. query types, parameter names, domain terms). Surfaces in `info.x-keywords` and the landing page response schema. Distinct from `document_metadata.keywords`, which are for the OGC PDF header |
272
278
  | `server_url` | string | no | Documentation only — not written to the profile OpenAPI |
279
+ | `allow_post_queries` | bool | no | When `true`, generates `POST` alongside `GET` for all EDR data query endpoints. Defaults to `false` |
273
280
  | `collections` | list | yes | One or more EDR collections (see below) |
274
281
  | `required_conformance_classes` | list | no | Conformance classes implementations must declare. Defaults to EDR Core |
275
282
  | `extent_requirements` | object | no | Profile-level CRS/TRS/VRS constraints (see below) |
@@ -184,6 +184,10 @@ A profile config is a YAML file. The full JSON Schema is at [`profile.schema.jso
184
184
  name: my_profile # lowercase, a-z 0-9 _ only
185
185
  title: My EDR Profile
186
186
  version: "1.0"
187
+ description: Brief description of what this service profile provides.
188
+ keywords:
189
+ - my-parameter
190
+ - my-domain
187
191
 
188
192
  required_conformance_classes:
189
193
  - "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/core"
@@ -224,7 +228,10 @@ collections:
224
228
  | `name` | string | yes | Lowercase `a-z 0-9 _`. Drives OGC URIs and OpenAPI `operationId`s |
225
229
  | `title` | string | yes | Human-readable profile title |
226
230
  | `version` | string | no | Defaults to `"1.0"` |
231
+ | `description` | string | no | Human-readable description of the service profile. Surfaces in the OpenAPI `info.description` and the landing page response schema |
232
+ | `keywords` | list | no | Service-level keywords (e.g. query types, parameter names, domain terms). Surfaces in `info.x-keywords` and the landing page response schema. Distinct from `document_metadata.keywords`, which are for the OGC PDF header |
227
233
  | `server_url` | string | no | Documentation only — not written to the profile OpenAPI |
234
+ | `allow_post_queries` | bool | no | When `true`, generates `POST` alongside `GET` for all EDR data query endpoints. Defaults to `false` |
228
235
  | `collections` | list | yes | One or more EDR collections (see below) |
229
236
  | `required_conformance_classes` | list | no | Conformance classes implementations must declare. Defaults to EDR Core |
230
237
  | `extent_requirements` | object | no | Profile-level CRS/TRS/VRS constraints (see below) |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "oapi-profile-builder"
7
- version = "2.3.0"
7
+ version = "2.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" }
@@ -89,7 +89,32 @@ _LINK_SCHEMA = {
89
89
  _LINKS_ARRAY = {"type": "array", "items": _LINK_SCHEMA}
90
90
 
91
91
  # Landing page response with required profile link per REQ_publishing
92
- def _landing_page_schema(profile_uri: str) -> dict:
92
+ def _landing_page_schema(profile_uri: str, title: str = "", description: str = "", keywords: list | None = None) -> dict:
93
+ schema_props: dict = {
94
+ "links": {
95
+ "type": "array",
96
+ "items": _LINK_SCHEMA,
97
+ "contains": {
98
+ "type": "object",
99
+ "required": ["href", "rel"],
100
+ "properties": {
101
+ "rel": {"const": "profile"},
102
+ "href": {"const": profile_uri},
103
+ },
104
+ },
105
+ },
106
+ }
107
+ if title:
108
+ schema_props["title"] = {"type": "string", "const": title}
109
+ if description:
110
+ schema_props["description"] = {"type": "string"}
111
+ if keywords:
112
+ schema_props["keywords"] = {
113
+ "type": "array",
114
+ "items": {"type": "string"},
115
+ "contains": {"enum": keywords},
116
+ }
117
+
93
118
  return {
94
119
  "description": "Landing page",
95
120
  "content": {
@@ -97,23 +122,10 @@ def _landing_page_schema(profile_uri: str) -> dict:
97
122
  "schema": {
98
123
  "type": "object",
99
124
  "required": ["links"],
100
- "properties": {
101
- "links": {
102
- "type": "array",
103
- "items": _LINK_SCHEMA,
104
- "contains": {
105
- "type": "object",
106
- "required": ["href", "rel"],
107
- "properties": {
108
- "rel": {"const": "profile"},
109
- "href": {"const": profile_uri}
110
- }
111
- }
112
- }
113
- }
125
+ "properties": schema_props,
114
126
  }
115
127
  }
116
- }
128
+ },
117
129
  }
118
130
 
119
131
  _R200_CONFORMANCE = {
@@ -823,7 +835,12 @@ def _collection_paths(coll: Collection, examples: dict | None = None,
823
835
 
824
836
 
825
837
  def _core_paths(profile: ServiceProfile) -> dict:
826
- landing_response = _landing_page_schema(profile.req_uri)
838
+ landing_response = _landing_page_schema(
839
+ profile.req_uri,
840
+ title=profile.title,
841
+ description=profile.description or "",
842
+ keywords=profile.keywords or None,
843
+ )
827
844
 
828
845
  # Conformance response with required conformance classes
829
846
  conformance_response = _R200_CONFORMANCE.copy()
@@ -1016,8 +1033,9 @@ def build_openapi(profile: ServiceProfile) -> dict:
1016
1033
  "info": {
1017
1034
  "title": profile.title,
1018
1035
  "version": profile.version,
1019
- "description": f"OGC API - EDR Part 3 Service Profile: {profile.title}",
1036
+ "description": profile.description or f"OGC API - EDR Part 3 Service Profile: {profile.title}",
1020
1037
  "x-ogc-profile": profile.req_uri,
1038
+ "x-keywords": profile.keywords if profile.keywords else [],
1021
1039
  "contact": contact,
1022
1040
  },
1023
1041
  # Per OGC API - EDR Part 3 REQ_publishing: this profile is implementation-independent.
@@ -60,6 +60,7 @@ from pydantic import AwareDatetime, BaseModel, Field, field_validator, model_val
60
60
  # ---------------------------------------------------------------------------
61
61
 
62
62
  from edr_pydantic.base_model import EdrBaseModel # noqa: E402 — after stdlib imports
63
+ from edr_pydantic.parameter import Parameters # noqa: E402
63
64
 
64
65
 
65
66
  class TemporalWithNullBounds(EdrBaseModel):
@@ -80,18 +81,32 @@ class ExtentWithNullBounds(EDRExtent):
80
81
 
81
82
  class Collection(EDRCollection):
82
83
  """
83
- EDR Collection with a null-aware temporal extent.
84
+ EDR Collection with a null-aware temporal extent and optional parameter_names.
84
85
 
85
- Identical to edr_pydantic.collections.Collection except that
86
- extent uses ExtentWithNullBounds so open-ended intervals like
87
- ["2020-01-01T00:00:00Z", null] are accepted.
86
+ Differences from edr_pydantic.collections.Collection:
88
87
 
89
- post_queries controls whether POST operations are generated for this
90
- collection's data query endpoints. None means inherit the profile-level
91
- allow_post_queries default. Set to True or False to override per-collection.
88
+ - extent uses ExtentWithNullBounds so open-ended intervals like
89
+ ["2020-01-01T00:00:00Z", null] are accepted (spec-compliant).
90
+
91
+ - parameter_names is Optional (default None). edr-pydantic marks it as
92
+ required, but OGC API - EDR Part 3 allows a profile to define the
93
+ *schema* for parameter objects via parameter_schema without mandating
94
+ any specific parameter names in the profile document itself.
95
+
96
+ - post_queries controls whether POST operations are generated for this
97
+ collection's data query endpoints. None means inherit the profile-level
98
+ allow_post_queries default. Set to True or False to override per-collection.
92
99
  """
93
100
 
94
101
  extent: Optional[ExtentWithNullBounds] = None # type: ignore[assignment]
102
+ parameter_names: Optional[Parameters] = Field( # type: ignore[assignment]
103
+ default=None,
104
+ description=(
105
+ "Map of parameter id → Parameter object. "
106
+ "Optional — omit when using parameter_schema to describe the structure "
107
+ "without mandating specific parameter names."
108
+ ),
109
+ )
95
110
  post_queries: Optional[bool] = Field(
96
111
  default=None,
97
112
  description=(
@@ -225,6 +240,22 @@ class ServiceProfile(BaseModel):
225
240
  name: Annotated[str, Field(pattern=r"^[a-z0-9_]+$")]
226
241
  title: str
227
242
  version: str = "1.0"
243
+ description: str | None = Field(
244
+ default=None,
245
+ description=(
246
+ "Human-readable description of the service profile. Surfaces in the "
247
+ "OpenAPI info block and the landing page response."
248
+ ),
249
+ )
250
+ keywords: list[str] = Field(
251
+ default_factory=list,
252
+ description=(
253
+ "Service-level keywords describing what this profile provides. "
254
+ "Surfaces in the OpenAPI info block (as x-keywords) and the landing "
255
+ "page response. Distinct from document_metadata.keywords, which are "
256
+ "for the OGC PDF header."
257
+ ),
258
+ )
228
259
  server_url: str | None = Field(default=None, description="Base URL for implementation (not used in profile OpenAPI per standard)")
229
260
  collections: list[Collection] = Field(min_length=1)
230
261
  collection_examples: dict[str, dict] = Field(default_factory=dict)
@@ -311,13 +342,11 @@ class ServiceProfile(BaseModel):
311
342
  if not coll.parameter_names:
312
343
  continue
313
344
  for param_name, param in coll.parameter_names.root.items():
314
- # Check if unit is specified
315
345
  if not hasattr(param, 'unit') or param.unit is None:
316
346
  raise ValueError(
317
347
  f"Parameter '{param_name}' in collection '{coll.id}' must specify unit "
318
348
  f"(required by OGC API - EDR Part 3 REQ_parameter-names)"
319
349
  )
320
- # Check if observedProperty is specified (already required by edr-pydantic)
321
350
  if not hasattr(param, 'observedProperty') or param.observedProperty is None:
322
351
  raise ValueError(
323
352
  f"Parameter '{param_name}' in collection '{coll.id}' must specify observedProperty"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oapi-profile-builder
3
- Version: 2.3.0
3
+ Version: 2.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
@@ -229,6 +229,10 @@ A profile config is a YAML file. The full JSON Schema is at [`profile.schema.jso
229
229
  name: my_profile # lowercase, a-z 0-9 _ only
230
230
  title: My EDR Profile
231
231
  version: "1.0"
232
+ description: Brief description of what this service profile provides.
233
+ keywords:
234
+ - my-parameter
235
+ - my-domain
232
236
 
233
237
  required_conformance_classes:
234
238
  - "http://www.opengis.net/spec/ogcapi-edr-1/1.0/conf/core"
@@ -269,7 +273,10 @@ collections:
269
273
  | `name` | string | yes | Lowercase `a-z 0-9 _`. Drives OGC URIs and OpenAPI `operationId`s |
270
274
  | `title` | string | yes | Human-readable profile title |
271
275
  | `version` | string | no | Defaults to `"1.0"` |
276
+ | `description` | string | no | Human-readable description of the service profile. Surfaces in the OpenAPI `info.description` and the landing page response schema |
277
+ | `keywords` | list | no | Service-level keywords (e.g. query types, parameter names, domain terms). Surfaces in `info.x-keywords` and the landing page response schema. Distinct from `document_metadata.keywords`, which are for the OGC PDF header |
272
278
  | `server_url` | string | no | Documentation only — not written to the profile OpenAPI |
279
+ | `allow_post_queries` | bool | no | When `true`, generates `POST` alongside `GET` for all EDR data query endpoints. Defaults to `false` |
273
280
  | `collections` | list | yes | One or more EDR collections (see below) |
274
281
  | `required_conformance_classes` | list | no | Conformance classes implementations must declare. Defaults to EDR Core |
275
282
  | `extent_requirements` | object | no | Profile-level CRS/TRS/VRS constraints (see below) |