Skip to main content

A Python library for validating OpenAPI documents published by OGC API servers

Project description

OGC API Registry Validator

PyPI version Python versions License CI Docs PyPI Downloads Code style: Ruff Type checked: mypy Pydantic v2

A Python library for validating OpenAPI documents published by OGC API servers against OGC specification requirements.

Why This Library?

OGC API standards (Features, Tiles, Processes, Records, etc.) define specific requirements for the OpenAPI documents that servers must publish. These requirements include:

  • Required endpoints (e.g., /collections, /conformance)
  • Required HTTP operations (GET, POST, etc.)
  • Conformance class declarations
  • Response schemas and content types

This library performs static validation of these OpenAPI documents, helping you verify that your OGC API server's published specification meets the standard requirements before deployment.

Features

  • OGC API Validation: Validate against OGC API - Features, Tiles, Processes, Records, Coverages, EDR, Maps, Styles, Routes
  • Conformance-Based Detection: Automatically detect API type from conformance classes
  • Error Severity Levels: Distinguish between critical errors, warnings, and informational messages
  • Extensible Strategy Pattern: Add custom validation strategies for new specifications
  • Async Support: Full async/await support for high-performance validation

Installation

pip install ogcapi-registry

Or with uv:

uv add ogcapi-registry

Quick Start

Validating an OGC API Server

from ogcapi_registry import (
    OpenAPIClient,
    validate_ogc_api,
    parse_conformance_classes,
)

# Fetch the OpenAPI document from your server
client = OpenAPIClient()
openapi_doc, metadata = client.fetch("https://demo.pygeoapi.io/master/openapi")

# Parse conformance classes (usually from /conformance endpoint)
conformance_uris = [
    "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core",
    "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson",
    "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30",
]
conformance_classes = parse_conformance_classes(conformance_uris)

# Validate against OGC API requirements
result = validate_ogc_api(openapi_doc, conformance_classes)

if result.is_valid:
    print("OpenAPI document is fully compliant!")
else:
    # Check error severity
    for error in result.critical_errors:
        print(f"CRITICAL: {error['message']}")

    for warning in result.warnings:
        print(f"WARNING: {warning['message']}")

Understanding Error Severity

The library classifies validation errors by severity:

from ogcapi_registry import ErrorSeverity

# Critical errors: Must be fixed for OGC compliance
result.critical_errors  # Missing required endpoints, wrong HTTP methods

# Warnings: Should be fixed but API may still function
result.warnings  # Missing recommended features like CRS support

# Info: Optional improvements
result.info_errors  # Missing optional features like filtering

# Check if API is compliant (no critical errors)
if result.is_compliant:
    print("API meets minimum OGC requirements")

Automatic API Type Detection

from ogcapi_registry import detect_api_types, get_primary_api_type

# Detect all API types from conformance classes
api_types = detect_api_types(conformance_classes)
# e.g., {OGCAPIType.FEATURES, OGCAPIType.TILES}

# Get the primary (most specific) API type
primary = get_primary_api_type(conformance_classes)
# e.g., OGCAPIType.FEATURES

Application Example: CI/CD Validation

Integrate OGC API validation into your deployment pipeline to catch specification errors before they reach production:

#!/usr/bin/env python
"""validate_ogc_server.py - CI/CD validation script"""

import sys
import httpx
from ogcapi_registry import (
    OpenAPIClient,
    validate_ogc_api,
    parse_conformance_classes,
)


def validate_server(base_url: str) -> bool:
    """Validate an OGC API server's OpenAPI document."""

    # 1. Fetch conformance classes
    response = httpx.get(f"{base_url}/conformance")
    response.raise_for_status()
    conformance_uris = response.json().get("conformsTo", [])

    if not conformance_uris:
        print("ERROR: No conformance classes declared")
        return False

    conformance_classes = parse_conformance_classes(conformance_uris)
    print(f"Found {len(conformance_classes)} conformance classes")

    # 2. Fetch and validate OpenAPI document
    client = OpenAPIClient()
    openapi_doc, metadata = client.fetch(f"{base_url}/openapi")

    print(f"Validating OpenAPI {openapi_doc.get('openapi', 'unknown')}")

    # 3. Run OGC API validation
    result = validate_ogc_api(openapi_doc, conformance_classes)

    # 4. Report results
    print(f"\n{'='*50}")
    print(f"Validation Result: {'PASSED' if result.is_valid else 'FAILED'}")
    print(f"{'='*50}")

    if result.critical_errors:
        print(f"\nCritical Errors ({len(result.critical_errors)}):")
        for err in result.critical_errors:
            print(f"  - {err['path']}: {err['message']}")

    if result.warnings:
        print(f"\nWarnings ({len(result.warnings)}):")
        for warn in result.warnings:
            print(f"  - {warn['path']}: {warn['message']}")

    summary = result.get_summary()
    print(f"\nSummary: {summary['critical']} critical, "
          f"{summary['warning']} warnings, {summary['info']} info")

    # Return True only if no critical errors
    return result.is_compliant


if __name__ == "__main__":
    server_url = sys.argv[1] if len(sys.argv) > 1 else "https://demo.pygeoapi.io/master"

    success = validate_server(server_url)
    sys.exit(0 if success else 1)

Use in GitHub Actions:

- name: Validate OGC API Compliance
  run: python validate_ogc_server.py ${{ env.SERVER_URL }}

Supported OGC API Standards

Standard Strategy Class Key Validations
OGC API - Common CommonStrategy Landing page, conformance, API definition
OGC API - Features FeaturesStrategy Collections, items, bbox, CRS
OGC API - Tiles TilesStrategy Tile matrix sets, tile endpoints
OGC API - Processes ProcessesStrategy Process list, execution, jobs
OGC API - Records RecordsStrategy Catalog, record queries
OGC API - Coverages CoveragesStrategy Coverage data access
OGC API - EDR EDRStrategy Environmental data queries
OGC API - Maps MapsStrategy Map rendering endpoints
OGC API - Styles StylesStrategy Style management
OGC API - Routes RoutesStrategy Routing endpoints

Advanced Usage

Custom Validation Strategy

from ogcapi_registry import ValidationStrategy, OGCAPIType, ValidationResult

class MyCustomStrategy(ValidationStrategy):
    """Custom validation for organization-specific requirements."""

    api_type = OGCAPIType.FEATURES

    def validate(self, document, conformance_classes):
        errors = []

        # Add custom validation logic
        if "/health" not in document.get("paths", {}):
            errors.append({
                "path": "paths",
                "message": "Missing /health endpoint (org requirement)",
                "severity": "warning",
            })

        return ValidationResult.success() if not errors else ValidationResult.failure(errors)

Async Validation

import asyncio
from ogcapi_registry import AsyncOpenAPIClient, validate_ogc_api

async def validate_multiple_servers(urls: list[str]):
    client = AsyncOpenAPIClient()

    async def validate_one(url):
        doc, _ = await client.fetch(f"{url}/openapi")
        # ... fetch conformance and validate
        return url, result

    results = await asyncio.gather(*[validate_one(url) for url in urls])
    return dict(results)

Documentation

Full documentation: https://francbartoli.github.io/ogcapi-registry/

Development

# Clone and install
git clone https://github.com/francbartoli/ogcapi-registry.git
cd ogcapi-registry
uv sync --all-extras --dev

# Run tests
uv run pytest -v

# Run linting
uv run ruff check src/ tests/
uv run mypy src/ogcapi_registry

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ogcapi_registry-0.1.1.tar.gz (32.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ogcapi_registry-0.1.1-py3-none-any.whl (44.3 kB view details)

Uploaded Python 3

File details

Details for the file ogcapi_registry-0.1.1.tar.gz.

File metadata

  • Download URL: ogcapi_registry-0.1.1.tar.gz
  • Upload date:
  • Size: 32.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ogcapi_registry-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9894e23979f6d396774229eef7735f37bd599676f4a28515ded2c348d56163c0
MD5 b24edb57a53a369fcb95f948dc8b2fff
BLAKE2b-256 627d1a3f5657c687b1b08d5b2588213abffd450d23a7977accc408699f4d5cb7

See more details on using hashes here.

Provenance

The following attestation bundles were made for ogcapi_registry-0.1.1.tar.gz:

Publisher: release.yml on francbartoli/ogcapi-registry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ogcapi_registry-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for ogcapi_registry-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 96fdc157b67e226a74e2fed45fc518702de62529a0ef34288464ce5456a8df69
MD5 42a2f6466e3b03be0378621eef0eaeda
BLAKE2b-256 97347f234a9c51dcc7371821b1087552e3ba8bed79d09433072c49d22a688974

See more details on using hashes here.

Provenance

The following attestation bundles were made for ogcapi_registry-0.1.1-py3-none-any.whl:

Publisher: release.yml on francbartoli/ogcapi-registry

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page