Repository: spacetelescope/stdatamodels (language: python)

Issue:
Add test to check all datamodel schemas
As came up https://github.com/spacetelescope/stdatamodels/pull/320#pullrequestreview-2290621622

It could be useful to do some basic schema checks for the datamodels schemas. These could include:
- ~a call to `asdf.schema.check_schema`~ EDIT: this is already handled by pytest-asdf
- checking if all schema keywords are in expected and understood places


Discussion / hints:

Fix patch:
diff --git a/changes/327.bugfix.rst b/changes/327.bugfix.rst
new file mode 100644
index 00000000..159e49c9
--- /dev/null
+++ b/changes/327.bugfix.rst
@@ -0,0 +1,1 @@
+Fix invalid abvegaoffset and coords schemas.
diff --git a/pyproject.toml b/pyproject.toml
index 0eaaf7ce..cc8f2136 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -45,6 +45,7 @@ jwst_pipeline = "stdatamodels.jwst.transforms.integration:get_resource_mappings"
 [project.optional-dependencies]
 test = [
     "psutil",
+    "pyyaml",
     "pytest>=4.6.0",
     "pytest-doctestplus",
     "crds>=11.17.1",
diff --git a/src/stdatamodels/jwst/datamodels/schemas/abvegaoffset.schema.yaml b/src/stdatamodels/jwst/datamodels/schemas/abvegaoffset.schema.yaml
index 2f86b9be..f32ec8e4 100644
--- a/src/stdatamodels/jwst/datamodels/schemas/abvegaoffset.schema.yaml
+++ b/src/stdatamodels/jwst/datamodels/schemas/abvegaoffset.schema.yaml
@@ -10,18 +10,4 @@ allOf:
     abvega_offset:
       title: Offsets to convert AB to Vega magnitudes
       type: object
-      properties:
-        abvega_offset:
-          title: AB_mag - Vega_mag
-          type: number
-        anyOf:
-          detector:
-            title: Detector name
-            type: string
-          filter:
-            title: Filter wheel element name
-            type: string
-          pupil:
-            title: Pupil wheel element name
-            type: string
 ...
diff --git a/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-0.7.0.yaml b/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-0.7.0.yaml
index 18d655fd..87504a38 100644
--- a/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-0.7.0.yaml
+++ b/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-0.7.0.yaml
@@ -29,7 +29,7 @@ examples:
 
 allOf:
   - $ref: "http://stsci.edu/schemas/asdf/transform/transform-1.1.0"
-  - object:
+  - type: object
     properties:
       model_type:
         description: |
diff --git a/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.0.0.yaml b/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.0.0.yaml
index a2db1b6f..b209e082 100644
--- a/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.0.0.yaml
+++ b/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.0.0.yaml
@@ -29,7 +29,7 @@ examples:
 
 allOf:
   - $ref: "http://stsci.edu/schemas/asdf/transform/transform-1.2.0"
-  - object:
+  - type: object
     properties:
       model_type:
         description: |
diff --git a/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.1.0.yaml b/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.1.0.yaml
index f5f27479..4b4fbb3d 100644
--- a/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.1.0.yaml
+++ b/src/stdatamodels/jwst/transforms/resources/schemas/stsci.edu/jwst_pipeline/coords-1.1.0.yaml
@@ -28,7 +28,7 @@ examples:
 
 allOf:
   - $ref: "http://stsci.edu/schemas/asdf/transform/transform-1.3.0"
-  - object:
+  - type: object
     properties:
       model_type:
         description: |


Test patch:
diff --git a/src/stdatamodels/jwst/_tests/__init__.py b/src/stdatamodels/jwst/_tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/stdatamodels/jwst/_tests/test_schemas.py b/src/stdatamodels/jwst/_tests/test_schemas.py
new file mode 100644
index 00000000..d5ee0ed9
--- /dev/null
+++ b/src/stdatamodels/jwst/_tests/test_schemas.py
@@ -0,0 +1,81 @@
+from pathlib import Path
+
+import asdf
+import pytest
+import yaml
+
+from stdatamodels.fits_support import _get_validators
+from stdatamodels.schema import walk_schema
+
+
+# relative paths to schema directories
+SCHEMA_RELATIVE_PATHS = [
+    "../datamodels/schemas",
+    "../transforms/resources/schemas/stsci.edu/jwst_pipeline",
+]
+
+
+def _get_schema_ids():
+    root_path = Path(__file__).parent
+    schema_ids = []
+    for schema_relative_path in SCHEMA_RELATIVE_PATHS:
+        path = root_path / schema_relative_path
+        for schema_path in path.glob("*.yaml"):
+            with open(schema_path, "r") as f:
+                schema_ids.append(yaml.load(f, yaml.SafeLoader)["id"])
+    return schema_ids
+
+
+SCHEMA_IDS = _get_schema_ids()
+
+
+@pytest.fixture(scope="module")
+def known_validators():
+    # what validators do we understand?
+    # since we aren't going to use these we can feed it
+    # anything in place of a valid hdulist
+    class Foo:
+        pass
+
+    validators = _get_validators(Foo())[0]
+    known_validators = set(validators.keys())
+    return known_validators
+
+
+@pytest.fixture(scope="module")
+def valid_keywords(known_validators):
+    return known_validators | {
+        "id",
+        "$schema",
+        "title",
+        "description",
+        "default",
+        "examples",
+        "blend_table",
+        "blend_rule",
+        "fits_hdu",
+        "definitions",
+        "allow_extra_columns",
+    }
+
+
+def test_found_schemas():
+    """
+    Make sure we found some schemas
+    """
+    assert SCHEMA_IDS
+
+
+@pytest.mark.parametrize("schema_id", SCHEMA_IDS)
+def test_schema_contains_only_known_keywords(schema_id, valid_keywords):
+    # load the schema from asdf instead of the file to
+    # verify that asdf knows about the schema
+    schema = asdf.schema.load_schema(schema_id)
+
+
+    def callback(schema, path, combiner, ctx, recurse):
+        extra = schema.keys() - ctx["valid_keywords"]
+        assert not extra, f"{extra} found at {path} in {schema_id}"
+
+    ctx = {"valid_keywords": valid_keywords}
+    walk_schema(schema, callback, ctx)