Source code for sqlrules.plugins
from __future__ import annotations
from typing import Any, Protocol, runtime_checkable
from sqlrules.errors import PluginError
from sqlrules.translators import TranslatorRegistry
PLUGIN_API_VERSION = "1"
"""Version of the translator plugin contract.
API v1 covers:
- ``SQLRulesPlugin`` shape (``name``, ``api_version``, ``register``)
- ``TranslatorRegistry.register_constraint`` / ``register`` / ``copy`` /
``operators`` / ``lookup`` / ``translate``
- Translator signature ``(Constraint, ColumnElement, CompilationContext)``
- IR value types for built-in operators, including ``PatternSpec`` for
``pattern`` (use ``pattern_text()``; do not assume ``constraint.value``
is a bare ``str``) and ``TypeSpec`` for ``type_check`` (use ``type_spec()``)
- Stable marker operator names (``json_contains``, ``array_contains``, …)
Bump this string on incompatible changes to any of the above. Package
minor bumps alone do not change ``PLUGIN_API_VERSION``.
"""
[docs]
@runtime_checkable
class SQLRulesPlugin(Protocol):
"""Explicit extension that registers translators onto a registry."""
name: str
api_version: str
[docs]
def register(self, registry: TranslatorRegistry) -> None:
"""Register constraint translators on ``registry``."""
def validate_plugin(plugin: Any) -> SQLRulesPlugin:
"""Validate a plugin object against the versioned plugin API."""
if isinstance(plugin, type):
raise PluginError(
message=(
f"Plugin {plugin!r} is a class; pass an instance "
f"(e.g. {getattr(plugin, '__name__', 'Plugin')}())."
),
plugin=plugin,
)
if not isinstance(plugin, SQLRulesPlugin):
raise PluginError(
message=(
f"Plugin {plugin!r} does not implement SQLRulesPlugin "
"(requires name, api_version, and register(registry))."
),
plugin=plugin,
)
name = getattr(plugin, "name", None)
if not isinstance(name, str) or not name:
raise PluginError(
message=f"Plugin {plugin!r} must declare a non-empty string name.",
plugin=plugin,
)
api_version = getattr(plugin, "api_version", None)
if api_version != PLUGIN_API_VERSION:
raise PluginError(
message=(
f"Plugin {name!r} declares api_version={api_version!r}, "
f"but SQLRules plugin API is {PLUGIN_API_VERSION!r}."
),
plugin=plugin,
)
register = getattr(plugin, "register", None)
if not callable(register):
raise PluginError(
message=f"Plugin {name!r} must provide a callable register(registry) method.",
plugin=plugin,
)
return plugin