integrations: Fix config_options type.

The “validator” component of the tuple does not follow the Validator
contract as of 7e9db327b3 (#15498).
Define a separate type for it.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2022-05-31 15:34:34 -07:00 committed by Tim Abbott
parent c944adfcc6
commit 74e94ae78c
3 changed files with 8 additions and 7 deletions

View File

@ -1,6 +1,6 @@
import os import os
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Sequence, Tuple from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
from django.contrib.staticfiles.storage import staticfiles_storage from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import path from django.urls import path
@ -10,7 +10,6 @@ from django.utils.module_loading import import_string
from django.utils.translation import gettext as gettext_lazy from django.utils.translation import gettext as gettext_lazy
from zerver.lib.storage import static_path from zerver.lib.storage import static_path
from zerver.lib.types import Validator
"""This module declares all of the (documented) integrations available """This module declares all of the (documented) integrations available
in the Zulip server. The Integration class is used as part of in the Zulip server. The Integration class is used as part of
@ -31,6 +30,8 @@ Over time, we expect this registry to grow additional convenience
features for writing and configuring integrations efficiently. features for writing and configuring integrations efficiently.
""" """
OptionValidator = Callable[[str, str], Optional[str]]
CATEGORIES: Dict[str, Promise] = { CATEGORIES: Dict[str, Promise] = {
"meta-integration": gettext_lazy("Integration frameworks"), "meta-integration": gettext_lazy("Integration frameworks"),
"continuous-integration": gettext_lazy("Continuous integration"), "continuous-integration": gettext_lazy("Continuous integration"),
@ -66,7 +67,7 @@ class Integration:
doc: Optional[str] = None, doc: Optional[str] = None,
stream_name: Optional[str] = None, stream_name: Optional[str] = None,
legacy: bool = False, legacy: bool = False,
config_options: Sequence[Tuple[str, str, Validator[object]]] = [], config_options: Sequence[Tuple[str, str, OptionValidator]] = [],
) -> None: ) -> None:
self.name = name self.name = name
self.client_name = client_name self.client_name = client_name
@ -188,7 +189,7 @@ class WebhookIntegration(Integration):
doc: Optional[str] = None, doc: Optional[str] = None,
stream_name: Optional[str] = None, stream_name: Optional[str] = None,
legacy: bool = False, legacy: bool = False,
config_options: Sequence[Tuple[str, str, Validator[object]]] = [], config_options: Sequence[Tuple[str, str, OptionValidator]] = [],
) -> None: ) -> None:
if client_name is None: if client_name is None:
client_name = self.DEFAULT_CLIENT_NAME.format(name=name.title()) client_name = self.DEFAULT_CLIENT_NAME.format(name=name.title())

View File

@ -101,7 +101,7 @@ def check_valid_bot_config(bot_type: int, service_name: str, config_data: Dict[s
for key, validator in config_options.items(): for key, validator in config_options.items():
value = config_data[key] value = config_data[key]
error = validator(key, value) error = validator(key, value)
if error: if error is not None:
raise JsonableError(_("Invalid {} value {} ({})").format(key, value, error)) raise JsonableError(_("Invalid {} value {} ({})").format(key, value, error))
elif bot_type == UserProfile.EMBEDDED_BOT: elif bot_type == UserProfile.EMBEDDED_BOT:

View File

@ -29,8 +29,8 @@ from zerver.models import (
# A test validator # A test validator
def _check_string(var_name: str, val: object) -> Optional[str]: def _check_string(var_name: str, val: str) -> Optional[str]:
if str(val).startswith("_"): if val.startswith("_"):
return f'{var_name} starts with a "_" and is hence invalid.' return f'{var_name} starts with a "_" and is hence invalid.'
return None return None