mirror of https://github.com/zulip/zulip.git
validator: Remove unused type_structure system.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
07fa63e0c8
commit
d6655689f5
|
@ -17,9 +17,6 @@ exclude_lines =
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# Don't require coverage for abstract methods; they're never called.
|
# Don't require coverage for abstract methods; they're never called.
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
# Don't require coverage for the USING_TYPE_STRUCTURE code paths
|
|
||||||
# These are only run in a special testing mode, so will fail normal coverage.
|
|
||||||
if USING_TYPE_STRUCTURE
|
|
||||||
# PEP 484 overloading syntax
|
# PEP 484 overloading syntax
|
||||||
^\s*\.\.\.
|
^\s*\.\.\.
|
||||||
|
|
||||||
|
|
|
@ -29,23 +29,9 @@ for any particular type of object.
|
||||||
'''
|
'''
|
||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import (
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Union, cast, overload
|
||||||
Any,
|
|
||||||
Callable,
|
|
||||||
Dict,
|
|
||||||
Iterable,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Set,
|
|
||||||
Tuple,
|
|
||||||
TypeVar,
|
|
||||||
Union,
|
|
||||||
cast,
|
|
||||||
overload,
|
|
||||||
)
|
|
||||||
|
|
||||||
import ujson
|
import ujson
|
||||||
from django.conf import settings
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import URLValidator, validate_email
|
from django.core.validators import URLValidator, validate_email
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -53,30 +39,12 @@ from django.utils.translation import ugettext as _
|
||||||
from zerver.lib.request import JsonableError, ResultT
|
from zerver.lib.request import JsonableError, ResultT
|
||||||
from zerver.lib.types import ProfileFieldData, Validator
|
from zerver.lib.types import ProfileFieldData, Validator
|
||||||
|
|
||||||
FuncT = TypeVar("FuncT", bound=Callable[..., object])
|
|
||||||
TypeStructure = TypeVar("TypeStructure")
|
|
||||||
|
|
||||||
USING_TYPE_STRUCTURE = settings.LOG_API_EVENT_TYPES
|
|
||||||
|
|
||||||
# The type_structure system is designed to support using the validators in
|
|
||||||
# test_events.py to create documentation for our event formats.
|
|
||||||
#
|
|
||||||
# Ultimately, it should be possible to do this with mypy rather than a
|
|
||||||
# parallel system.
|
|
||||||
def set_type_structure(type_structure: TypeStructure) -> Callable[[FuncT], FuncT]:
|
|
||||||
def _set_type_structure(func: FuncT) -> FuncT:
|
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
func.type_structure = type_structure # type: ignore[attr-defined] # monkey-patching
|
|
||||||
return func
|
|
||||||
return _set_type_structure
|
|
||||||
|
|
||||||
@set_type_structure("str")
|
|
||||||
def check_string(var_name: str, val: object) -> str:
|
def check_string(var_name: str, val: object) -> str:
|
||||||
if not isinstance(val, str):
|
if not isinstance(val, str):
|
||||||
raise ValidationError(_('{var_name} is not a string').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a string').format(var_name=var_name))
|
||||||
return val
|
return val
|
||||||
|
|
||||||
@set_type_structure("str")
|
|
||||||
def check_required_string(var_name: str, val: object) -> str:
|
def check_required_string(var_name: str, val: object) -> str:
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
if not s.strip():
|
if not s.strip():
|
||||||
|
@ -84,7 +52,6 @@ def check_required_string(var_name: str, val: object) -> str:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def check_string_in(possible_values: Union[Set[str], List[str]]) -> Validator[str]:
|
def check_string_in(possible_values: Union[Set[str], List[str]]) -> Validator[str]:
|
||||||
@set_type_structure("str")
|
|
||||||
def validator(var_name: str, val: object) -> str:
|
def validator(var_name: str, val: object) -> str:
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
if s not in possible_values:
|
if s not in possible_values:
|
||||||
|
@ -93,12 +60,10 @@ def check_string_in(possible_values: Union[Set[str], List[str]]) -> Validator[st
|
||||||
|
|
||||||
return validator
|
return validator
|
||||||
|
|
||||||
@set_type_structure("str")
|
|
||||||
def check_short_string(var_name: str, val: object) -> str:
|
def check_short_string(var_name: str, val: object) -> str:
|
||||||
return check_capped_string(50)(var_name, val)
|
return check_capped_string(50)(var_name, val)
|
||||||
|
|
||||||
def check_capped_string(max_length: int) -> Validator[str]:
|
def check_capped_string(max_length: int) -> Validator[str]:
|
||||||
@set_type_structure("str")
|
|
||||||
def validator(var_name: str, val: object) -> str:
|
def validator(var_name: str, val: object) -> str:
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
if len(s) > max_length:
|
if len(s) > max_length:
|
||||||
|
@ -110,7 +75,6 @@ def check_capped_string(max_length: int) -> Validator[str]:
|
||||||
return validator
|
return validator
|
||||||
|
|
||||||
def check_string_fixed_length(length: int) -> Validator[str]:
|
def check_string_fixed_length(length: int) -> Validator[str]:
|
||||||
@set_type_structure("str")
|
|
||||||
def validator(var_name: str, val: object) -> str:
|
def validator(var_name: str, val: object) -> str:
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
if len(s) != length:
|
if len(s) != length:
|
||||||
|
@ -121,11 +85,9 @@ def check_string_fixed_length(length: int) -> Validator[str]:
|
||||||
|
|
||||||
return validator
|
return validator
|
||||||
|
|
||||||
@set_type_structure("str")
|
|
||||||
def check_long_string(var_name: str, val: object) -> str:
|
def check_long_string(var_name: str, val: object) -> str:
|
||||||
return check_capped_string(500)(var_name, val)
|
return check_capped_string(500)(var_name, val)
|
||||||
|
|
||||||
@set_type_structure("date")
|
|
||||||
def check_date(var_name: str, val: object) -> str:
|
def check_date(var_name: str, val: object) -> str:
|
||||||
if not isinstance(val, str):
|
if not isinstance(val, str):
|
||||||
raise ValidationError(_('{var_name} is not a string').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a string').format(var_name=var_name))
|
||||||
|
@ -135,14 +97,12 @@ def check_date(var_name: str, val: object) -> str:
|
||||||
raise ValidationError(_('{var_name} is not a date').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a date').format(var_name=var_name))
|
||||||
return val
|
return val
|
||||||
|
|
||||||
@set_type_structure("int")
|
|
||||||
def check_int(var_name: str, val: object) -> int:
|
def check_int(var_name: str, val: object) -> int:
|
||||||
if not isinstance(val, int):
|
if not isinstance(val, int):
|
||||||
raise ValidationError(_('{var_name} is not an integer').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not an integer').format(var_name=var_name))
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def check_int_in(possible_values: List[int]) -> Validator[int]:
|
def check_int_in(possible_values: List[int]) -> Validator[int]:
|
||||||
@set_type_structure("int")
|
|
||||||
def validator(var_name: str, val: object) -> int:
|
def validator(var_name: str, val: object) -> int:
|
||||||
n = check_int(var_name, val)
|
n = check_int(var_name, val)
|
||||||
if n not in possible_values:
|
if n not in possible_values:
|
||||||
|
@ -151,19 +111,16 @@ def check_int_in(possible_values: List[int]) -> Validator[int]:
|
||||||
|
|
||||||
return validator
|
return validator
|
||||||
|
|
||||||
@set_type_structure("float")
|
|
||||||
def check_float(var_name: str, val: object) -> float:
|
def check_float(var_name: str, val: object) -> float:
|
||||||
if not isinstance(val, float):
|
if not isinstance(val, float):
|
||||||
raise ValidationError(_('{var_name} is not a float').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a float').format(var_name=var_name))
|
||||||
return val
|
return val
|
||||||
|
|
||||||
@set_type_structure("bool")
|
|
||||||
def check_bool(var_name: str, val: object) -> bool:
|
def check_bool(var_name: str, val: object) -> bool:
|
||||||
if not isinstance(val, bool):
|
if not isinstance(val, bool):
|
||||||
raise ValidationError(_('{var_name} is not a boolean').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a boolean').format(var_name=var_name))
|
||||||
return val
|
return val
|
||||||
|
|
||||||
@set_type_structure("str")
|
|
||||||
def check_color(var_name: str, val: object) -> str:
|
def check_color(var_name: str, val: object) -> str:
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
valid_color_pattern = re.compile(r'^#([a-fA-F0-9]{3,6})$')
|
valid_color_pattern = re.compile(r'^#([a-fA-F0-9]{3,6})$')
|
||||||
|
@ -173,12 +130,6 @@ def check_color(var_name: str, val: object) -> str:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def check_none_or(sub_validator: Validator[ResultT]) -> Validator[Optional[ResultT]]:
|
def check_none_or(sub_validator: Validator[ResultT]) -> Validator[Optional[ResultT]]:
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
type_structure = 'none_or_' + sub_validator.type_structure # type: ignore[attr-defined] # monkey-patching
|
|
||||||
else:
|
|
||||||
type_structure = None
|
|
||||||
|
|
||||||
@set_type_structure(type_structure)
|
|
||||||
def f(var_name: str, val: object) -> Optional[ResultT]:
|
def f(var_name: str, val: object) -> Optional[ResultT]:
|
||||||
if val is None:
|
if val is None:
|
||||||
return val
|
return val
|
||||||
|
@ -194,15 +145,6 @@ def check_list(sub_validator: None, length: Optional[int]=None) -> Validator[Lis
|
||||||
def check_list(sub_validator: Validator[ResultT], length: Optional[int]=None) -> Validator[List[ResultT]]:
|
def check_list(sub_validator: Validator[ResultT], length: Optional[int]=None) -> Validator[List[ResultT]]:
|
||||||
...
|
...
|
||||||
def check_list(sub_validator: Optional[Validator[ResultT]]=None, length: Optional[int]=None) -> Validator[List[ResultT]]:
|
def check_list(sub_validator: Optional[Validator[ResultT]]=None, length: Optional[int]=None) -> Validator[List[ResultT]]:
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
if sub_validator:
|
|
||||||
type_structure = [sub_validator.type_structure] # type: ignore[attr-defined] # monkey-patching
|
|
||||||
else:
|
|
||||||
type_structure = 'list' # type: ignore[assignment] # monkey-patching
|
|
||||||
else:
|
|
||||||
type_structure = None # type: ignore[assignment] # monkey-patching
|
|
||||||
|
|
||||||
@set_type_structure(type_structure)
|
|
||||||
def f(var_name: str, val: object) -> List[ResultT]:
|
def f(var_name: str, val: object) -> List[ResultT]:
|
||||||
if not isinstance(val, list):
|
if not isinstance(val, list):
|
||||||
raise ValidationError(_('{var_name} is not a list').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a list').format(var_name=var_name))
|
||||||
|
@ -240,9 +182,6 @@ def check_dict(required_keys: Iterable[Tuple[str, Validator[ResultT]]]=[],
|
||||||
*,
|
*,
|
||||||
value_validator: Optional[Validator[ResultT]]=None,
|
value_validator: Optional[Validator[ResultT]]=None,
|
||||||
_allow_only_listed_keys: bool=False) -> Validator[Dict[str, ResultT]]:
|
_allow_only_listed_keys: bool=False) -> Validator[Dict[str, ResultT]]:
|
||||||
type_structure: Dict[str, Any] = {}
|
|
||||||
|
|
||||||
@set_type_structure(type_structure)
|
|
||||||
def f(var_name: str, val: object) -> Dict[str, ResultT]:
|
def f(var_name: str, val: object) -> Dict[str, ResultT]:
|
||||||
if not isinstance(val, dict):
|
if not isinstance(val, dict):
|
||||||
raise ValidationError(_('{var_name} is not a dict').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a dict').format(var_name=var_name))
|
||||||
|
@ -257,23 +196,17 @@ def check_dict(required_keys: Iterable[Tuple[str, Validator[ResultT]]]=[],
|
||||||
))
|
))
|
||||||
vname = f'{var_name}["{k}"]'
|
vname = f'{var_name}["{k}"]'
|
||||||
sub_validator(vname, val[k])
|
sub_validator(vname, val[k])
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
type_structure[k] = sub_validator.type_structure # type: ignore[attr-defined] # monkey-patching
|
|
||||||
|
|
||||||
for k, sub_validator in optional_keys:
|
for k, sub_validator in optional_keys:
|
||||||
if k in val:
|
if k in val:
|
||||||
vname = f'{var_name}["{k}"]'
|
vname = f'{var_name}["{k}"]'
|
||||||
sub_validator(vname, val[k])
|
sub_validator(vname, val[k])
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
type_structure[k] = sub_validator.type_structure # type: ignore[attr-defined] # monkey-patching
|
|
||||||
|
|
||||||
if value_validator:
|
if value_validator:
|
||||||
for key in val:
|
for key in val:
|
||||||
vname = f'{var_name} contains a value that'
|
vname = f'{var_name} contains a value that'
|
||||||
valid_value = value_validator(vname, val[key])
|
valid_value = value_validator(vname, val[key])
|
||||||
assert val[key] is valid_value # To justify the unchecked cast below
|
assert val[key] is valid_value # To justify the unchecked cast below
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
type_structure['any'] = value_validator.type_structure # type: ignore[attr-defined] # monkey-patching
|
|
||||||
|
|
||||||
if _allow_only_listed_keys:
|
if _allow_only_listed_keys:
|
||||||
required_keys_set = {x[0] for x in required_keys}
|
required_keys_set = {x[0] for x in required_keys}
|
||||||
|
@ -302,12 +235,6 @@ def check_union(allowed_type_funcs: Iterable[Validator[ResultT]]) -> Validator[R
|
||||||
types for this variable.
|
types for this variable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if USING_TYPE_STRUCTURE:
|
|
||||||
type_structure = f'any("{[x.type_structure for x in allowed_type_funcs]}")' # type: ignore[attr-defined] # monkey-patching
|
|
||||||
else:
|
|
||||||
type_structure = None # type: ignore[assignment] # monkey-patching
|
|
||||||
|
|
||||||
@set_type_structure(type_structure)
|
|
||||||
def enumerated_type_check(var_name: str, val: object) -> ResultT:
|
def enumerated_type_check(var_name: str, val: object) -> ResultT:
|
||||||
for func in allowed_type_funcs:
|
for func in allowed_type_funcs:
|
||||||
try:
|
try:
|
||||||
|
@ -318,7 +245,6 @@ def check_union(allowed_type_funcs: Iterable[Validator[ResultT]]) -> Validator[R
|
||||||
return enumerated_type_check
|
return enumerated_type_check
|
||||||
|
|
||||||
def equals(expected_val: ResultT) -> Validator[ResultT]:
|
def equals(expected_val: ResultT) -> Validator[ResultT]:
|
||||||
@set_type_structure(f'equals("{str(expected_val)}")')
|
|
||||||
def f(var_name: str, val: object) -> ResultT:
|
def f(var_name: str, val: object) -> ResultT:
|
||||||
if val != expected_val:
|
if val != expected_val:
|
||||||
raise ValidationError(_('{variable} != {expected_value} ({value} is wrong)').format(
|
raise ValidationError(_('{variable} != {expected_value} ({value} is wrong)').format(
|
||||||
|
@ -327,14 +253,12 @@ def equals(expected_val: ResultT) -> Validator[ResultT]:
|
||||||
return cast(ResultT, val)
|
return cast(ResultT, val)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
@set_type_structure('str')
|
|
||||||
def validate_login_email(email: str) -> None:
|
def validate_login_email(email: str) -> None:
|
||||||
try:
|
try:
|
||||||
validate_email(email)
|
validate_email(email)
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
raise JsonableError(str(err.message))
|
raise JsonableError(str(err.message))
|
||||||
|
|
||||||
@set_type_structure('str')
|
|
||||||
def check_url(var_name: str, val: object) -> str:
|
def check_url(var_name: str, val: object) -> str:
|
||||||
# First, ensure val is a string
|
# First, ensure val is a string
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
|
@ -346,7 +270,6 @@ def check_url(var_name: str, val: object) -> str:
|
||||||
except ValidationError:
|
except ValidationError:
|
||||||
raise ValidationError(_('{var_name} is not a URL').format(var_name=var_name))
|
raise ValidationError(_('{var_name} is not a URL').format(var_name=var_name))
|
||||||
|
|
||||||
@set_type_structure('str')
|
|
||||||
def check_external_account_url_pattern(var_name: str, val: object) -> str:
|
def check_external_account_url_pattern(var_name: str, val: object) -> str:
|
||||||
s = check_string(var_name, val)
|
s = check_string(var_name, val)
|
||||||
|
|
||||||
|
@ -433,7 +356,6 @@ def check_widget_content(widget_content: object) -> Dict[str, Any]:
|
||||||
|
|
||||||
|
|
||||||
# Converter functions for use with has_request_variables
|
# Converter functions for use with has_request_variables
|
||||||
@set_type_structure('int')
|
|
||||||
def to_non_negative_int(s: str, max_int_size: int=2**32-1) -> int:
|
def to_non_negative_int(s: str, max_int_size: int=2**32-1) -> int:
|
||||||
x = int(s)
|
x = int(s)
|
||||||
if x < 0:
|
if x < 0:
|
||||||
|
@ -443,7 +365,6 @@ def to_non_negative_int(s: str, max_int_size: int=2**32-1) -> int:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def to_positive_or_allowed_int(allowed_integer: int) -> Callable[[str], int]:
|
def to_positive_or_allowed_int(allowed_integer: int) -> Callable[[str], int]:
|
||||||
@set_type_structure('int')
|
|
||||||
def convertor(s: str) -> int:
|
def convertor(s: str) -> int:
|
||||||
x = int(s)
|
x = int(s)
|
||||||
if x == allowed_integer:
|
if x == allowed_integer:
|
||||||
|
@ -453,7 +374,6 @@ def to_positive_or_allowed_int(allowed_integer: int) -> Callable[[str], int]:
|
||||||
return to_non_negative_int(s)
|
return to_non_negative_int(s)
|
||||||
return convertor
|
return convertor
|
||||||
|
|
||||||
@set_type_structure('any(List[int], str)]')
|
|
||||||
def check_string_or_int_list(var_name: str, val: object) -> Union[str, List[int]]:
|
def check_string_or_int_list(var_name: str, val: object) -> Union[str, List[int]]:
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
return val
|
return val
|
||||||
|
@ -463,7 +383,6 @@ def check_string_or_int_list(var_name: str, val: object) -> Union[str, List[int]
|
||||||
|
|
||||||
return check_list(check_int)(var_name, val)
|
return check_list(check_int)(var_name, val)
|
||||||
|
|
||||||
@set_type_structure('any(int, str)')
|
|
||||||
def check_string_or_int(var_name: str, val: object) -> Union[str, int]:
|
def check_string_or_int(var_name: str, val: object) -> Union[str, int]:
|
||||||
if isinstance(val, str) or isinstance(val, int):
|
if isinstance(val, str) or isinstance(val, int):
|
||||||
return val
|
return val
|
||||||
|
|
Loading…
Reference in New Issue