checks-schemas: Remove checks related to API docs.

When we move away from `data_types.py` in favor of using
`pydantic` to describe the shape of our event objects in
the events test (hopefully coming soon), then the code
I deleted here will no longer work.

The consequence of this change is that API docs may
diverge from the actual event types that we use, but
I believe there are better ways to manage this.

Also, the deleted code was particularly hard to debug
(and I say that as the original author). It probably
also causes friction for folks who want to update the
docs but who don't necessarily grok how the event tests
work under the legacy `data_types.py` regime.

Once we get pydantic types working, we can probably
just write a separate tool to validate against them
against the API docs using the `openapi-schema-pydantic`
package or something similar.
This commit is contained in:
Steve Howell
2025-01-01 15:09:21 +00:00
committed by Tim Abbott
parent ddd58b1a14
commit 7480c5f285

View File

@@ -10,7 +10,6 @@
# We compare the Python and OpenAPI schemas by converting the OpenAPI data
# into the event_schema style of types and the diffing the schemas.
import argparse
import difflib
import os
import subprocess
import sys
@@ -53,36 +52,7 @@ os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.test_settings"
django.setup()
from zerver.lib import event_schema
from zerver.lib.data_types import (
DictType,
EnumType,
ListType,
NumberType,
StringDictType,
UnionType,
make_checker,
schema,
)
from zerver.openapi.openapi import openapi_spec
# This list of exemptions represents details we should fix in Zulip's
# API structure and/or validators.
EXEMPT_OPENAPI_NAMES = [
# Additional keys(push_users_notify) due to bug in API.
"message_event",
# tuple handling
"muted_topics_event",
# bots, delivery_email, profile_data
"realm_user_add_event",
# OpenAPI is incomplete
"realm_update_dict_event",
]
# This is a list of events still documented in the OpenAPI that
# are deprecated and no longer checked in event_schema.py.
DEPRECATED_EVENTS = [
"realm_filters_event",
]
from zerver.lib.data_types import make_checker
def get_event_checker(event: dict[str, Any]) -> Callable[[str, dict[str, Any]], None] | None:
@@ -133,100 +103,11 @@ def verify_fixtures_are_sorted(names: list[str]) -> None:
)
def from_openapi(node: dict[str, Any]) -> Any:
"""Converts the OpenAPI data into event_schema.py style type
definitions for convenient comparison with the types used for backend
tests declared there."""
if "oneOf" in node:
return UnionType([from_openapi(n) for n in node["oneOf"]])
if node["type"] == "object":
if (
"additionalProperties" in node
# this might be a glitch in our current spec? or
# maybe I just understand it yet
and isinstance(node["additionalProperties"], dict)
):
return StringDictType(from_openapi(node["additionalProperties"]))
if "properties" not in node:
return dict
required_keys = []
for key, sub_node in node["properties"].items():
required_keys.append((key, from_openapi(sub_node)))
return DictType(required_keys)
if node["type"] == "boolean":
return bool
if node["type"] == "integer":
if "enum" in node:
return EnumType(node["enum"])
return int
if node["type"] == "number":
return NumberType()
if node["type"] == "string":
if "enum" in node:
return EnumType(node["enum"])
return str
if node["type"] == "array":
return ListType(from_openapi(node["items"]))
raise AssertionError("cannot handle node")
def validate_openapi_against_event_schema() -> None:
node = openapi_spec.openapi()["paths"]["/events"]["get"]["responses"]["200"]["content"][
"application/json"
]["schema"]["properties"]["events"]["items"]["oneOf"]
for sub_node in node:
name = sub_node["properties"]["type"]["enum"][0]
if "op" in sub_node["properties"]:
name += "_" + sub_node["properties"]["op"]["enum"][0]
name += "_event"
if not hasattr(event_schema, name):
if name not in DEPRECATED_EVENTS:
print("WARNING - NEED SCHEMA to match OpenAPI", name)
continue
openapi_type = from_openapi(sub_node)
openapi_schema = schema(name, openapi_type)
py_type = getattr(event_schema, name)
py_schema = schema(name, py_type)
if name in EXEMPT_OPENAPI_NAMES:
if openapi_schema == py_schema:
raise AssertionError(f"unnecessary exemption for {name}")
continue
if openapi_schema != py_schema:
print(f"py\n{py_schema}\n")
print(f"openapi\n{openapi_schema}\n")
for line in difflib.unified_diff(
py_schema.split("\n"),
openapi_schema.split("\n"),
fromfile="py",
tofile="openapi",
):
print(line)
raise AssertionError("openapi schemas disagree")
def run() -> None:
fixtures = read_fixtures()
verify_fixtures_are_sorted(list(fixtures.keys()))
for name, event in fixtures.items():
check_event(name, event)
validate_openapi_against_event_schema()
print("Successful check. All tests passed.")