decorator: Replace type: ignore with cast, avoid Any.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-06-23 17:10:50 -07:00
parent e582bbea4a
commit f2e7076e2a
8 changed files with 95 additions and 88 deletions

View File

@ -4,7 +4,7 @@ import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
from decimal import Decimal from decimal import Decimal
from functools import wraps from functools import wraps
from typing import Any, Callable, Dict, Optional, Tuple, TypeVar from typing import Callable, Dict, Optional, Tuple, TypeVar, cast
import stripe import stripe
import ujson import ujson
@ -39,7 +39,7 @@ billing_logger = logging.getLogger('corporate.stripe')
log_to_file(billing_logger, BILLING_LOG_PATH) log_to_file(billing_logger, BILLING_LOG_PATH)
log_to_file(logging.getLogger('stripe'), BILLING_LOG_PATH) log_to_file(logging.getLogger('stripe'), BILLING_LOG_PATH)
CallableT = TypeVar('CallableT', bound=Callable[..., Any]) CallableT = TypeVar('CallableT', bound=Callable[..., object])
MIN_INVOICED_LICENSES = 30 MIN_INVOICED_LICENSES = 30
MAX_INVOICED_LICENSES = 1000 MAX_INVOICED_LICENSES = 1000
@ -160,7 +160,7 @@ class StripeConnectionError(BillingError):
def catch_stripe_errors(func: CallableT) -> CallableT: def catch_stripe_errors(func: CallableT) -> CallableT:
@wraps(func) @wraps(func)
def wrapped(*args: Any, **kwargs: Any) -> Any: def wrapped(*args: object, **kwargs: object) -> object:
if settings.DEVELOPMENT and not settings.TEST_SUITE: # nocoverage if settings.DEVELOPMENT and not settings.TEST_SUITE: # nocoverage
if STRIPE_PUBLISHABLE_KEY is None: if STRIPE_PUBLISHABLE_KEY is None:
raise BillingError('missing stripe config', "Missing Stripe config. " raise BillingError('missing stripe config', "Missing Stripe config. "
@ -184,7 +184,7 @@ def catch_stripe_errors(func: CallableT) -> CallableT:
'stripe connection error', 'stripe connection error',
_("Something went wrong. Please wait a few seconds and try again.")) _("Something went wrong. Please wait a few seconds and try again."))
raise BillingError('other stripe error', BillingError.CONTACT_SUPPORT) raise BillingError('other stripe error', BillingError.CONTACT_SUPPORT)
return wrapped # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(CallableT, wrapped)
@catch_stripe_errors @catch_stripe_errors
def stripe_get_customer(stripe_customer_id: str) -> stripe.Customer: def stripe_get_customer(stripe_customer_id: str) -> stripe.Customer:

View File

@ -224,7 +224,7 @@ def mock_stripe(tested_timestamp_fields: Sequence[str]=[],
decorated_function = patch(mocked_function_name, side_effect=side_effect)(decorated_function) decorated_function = patch(mocked_function_name, side_effect=side_effect)(decorated_function)
@wraps(decorated_function) @wraps(decorated_function)
def wrapped(*args: Any, **kwargs: Any) -> Any: def wrapped(*args: object, **kwargs: object) -> object:
if generate_fixture: # nocoverage if generate_fixture: # nocoverage
delete_fixture_data(decorated_function) delete_fixture_data(decorated_function)
val = decorated_function(*args, **kwargs) val = decorated_function(*args, **kwargs)

View File

@ -4,7 +4,7 @@ import logging
import urllib import urllib
from functools import wraps from functools import wraps
from io import BytesIO from io import BytesIO
from typing import Any, Callable, Dict, Optional, Tuple, TypeVar, Union, cast from typing import Callable, Dict, Optional, Tuple, TypeVar, Union, cast
import django_otp import django_otp
import ujson import ujson
@ -105,38 +105,38 @@ def update_user_activity(request: HttpRequest, user_profile: UserProfile,
# Based on django.views.decorators.http.require_http_methods # Based on django.views.decorators.http.require_http_methods
def require_post(func: ViewFuncT) -> ViewFuncT: def require_post(func: ViewFuncT) -> ViewFuncT:
@wraps(func) @wraps(func)
def wrapper(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def wrapper(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
if request.method != "POST": if request.method != "POST":
err_method = request.method err_method = request.method
logging.warning('Method Not Allowed (%s): %s', err_method, request.path, logging.warning('Method Not Allowed (%s): %s', err_method, request.path,
extra={'status_code': 405, 'request': request}) extra={'status_code': 405, 'request': request})
return HttpResponseNotAllowed(["POST"]) return HttpResponseNotAllowed(["POST"])
return func(request, *args, **kwargs) return func(request, *args, **kwargs)
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapper) # https://github.com/python/mypy/issues/1927
def require_realm_owner(func: ViewFuncT) -> ViewFuncT: def require_realm_owner(func: ViewFuncT) -> ViewFuncT:
@wraps(func) @wraps(func)
def wrapper(request: HttpRequest, user_profile: UserProfile, *args: Any, **kwargs: Any) -> HttpResponse: def wrapper(request: HttpRequest, user_profile: UserProfile, *args: object, **kwargs: object) -> HttpResponse:
if not user_profile.is_realm_owner: if not user_profile.is_realm_owner:
raise OrganizationOwnerRequired() raise OrganizationOwnerRequired()
return func(request, user_profile, *args, **kwargs) return func(request, user_profile, *args, **kwargs)
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapper) # https://github.com/python/mypy/issues/1927
def require_realm_admin(func: ViewFuncT) -> ViewFuncT: def require_realm_admin(func: ViewFuncT) -> ViewFuncT:
@wraps(func) @wraps(func)
def wrapper(request: HttpRequest, user_profile: UserProfile, *args: Any, **kwargs: Any) -> HttpResponse: def wrapper(request: HttpRequest, user_profile: UserProfile, *args: object, **kwargs: object) -> HttpResponse:
if not user_profile.is_realm_admin: if not user_profile.is_realm_admin:
raise OrganizationAdministratorRequired() raise OrganizationAdministratorRequired()
return func(request, user_profile, *args, **kwargs) return func(request, user_profile, *args, **kwargs)
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapper) # https://github.com/python/mypy/issues/1927
def require_billing_access(func: ViewFuncT) -> ViewFuncT: def require_billing_access(func: ViewFuncT) -> ViewFuncT:
@wraps(func) @wraps(func)
def wrapper(request: HttpRequest, user_profile: UserProfile, *args: Any, **kwargs: Any) -> HttpResponse: def wrapper(request: HttpRequest, user_profile: UserProfile, *args: object, **kwargs: object) -> HttpResponse:
if not user_profile.is_realm_admin and not user_profile.is_billing_admin: if not user_profile.is_realm_admin and not user_profile.is_billing_admin:
raise JsonableError(_("Must be a billing administrator or an organization administrator")) raise JsonableError(_("Must be a billing administrator or an organization administrator"))
return func(request, user_profile, *args, **kwargs) return func(request, user_profile, *args, **kwargs)
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapper) # https://github.com/python/mypy/issues/1927
def get_client_name(request: HttpRequest) -> str: def get_client_name(request: HttpRequest) -> str:
@ -336,7 +336,7 @@ def api_key_only_webhook_view(
@has_request_variables @has_request_variables
@wraps(view_func) @wraps(view_func)
def _wrapped_func_arguments(request: HttpRequest, api_key: str=REQ(), def _wrapped_func_arguments(request: HttpRequest, api_key: str=REQ(),
*args: Any, **kwargs: Any) -> HttpResponse: *args: object, **kwargs: object) -> HttpResponse:
user_profile = validate_api_key(request, None, api_key, is_webhook=True, user_profile = validate_api_key(request, None, api_key, is_webhook=True,
client_name=full_webhook_client_name(webhook_client_name)) client_name=full_webhook_client_name(webhook_client_name))
@ -352,11 +352,11 @@ def api_key_only_webhook_view(
from zerver.lib.webhooks.common import notify_bot_owner_about_invalid_json from zerver.lib.webhooks.common import notify_bot_owner_about_invalid_json
notify_bot_owner_about_invalid_json(user_profile, webhook_client_name) notify_bot_owner_about_invalid_json(user_profile, webhook_client_name)
else: else:
kwargs = {'request': request, 'user_profile': user_profile} log_exception_to_webhook_logger(
if isinstance(err, UnexpectedWebhookEventType): request=request,
kwargs['unexpected_event'] = True user_profile=user_profile,
unexpected_event=isinstance(err, UnexpectedWebhookEventType),
log_exception_to_webhook_logger(**kwargs) )
raise err raise err
return _wrapped_func_arguments return _wrapped_func_arguments
@ -390,7 +390,7 @@ def user_passes_test(test_func: Callable[[HttpResponse], bool], login_url: Optio
""" """
def decorator(view_func: ViewFuncT) -> ViewFuncT: def decorator(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func, assigned=available_attrs(view_func)) @wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
if test_func(request): if test_func(request):
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
path = request.build_absolute_uri() path = request.build_absolute_uri()
@ -404,7 +404,7 @@ def user_passes_test(test_func: Callable[[HttpResponse], bool], login_url: Optio
path = request.get_full_path() path = request.get_full_path()
return redirect_to_login( return redirect_to_login(
path, resolved_login_url, redirect_field_name) path, resolved_login_url, redirect_field_name)
return _wrapped_view # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view) # https://github.com/python/mypy/issues/1927
return decorator return decorator
def logged_in_and_active(request: HttpRequest) -> bool: def logged_in_and_active(request: HttpRequest) -> bool:
@ -434,26 +434,26 @@ def do_login(request: HttpRequest, user_profile: UserProfile) -> None:
def log_view_func(view_func: ViewFuncT) -> ViewFuncT: def log_view_func(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
request._query = view_func.__name__ request._query = view_func.__name__
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def add_logging_data(view_func: ViewFuncT) -> ViewFuncT: def add_logging_data(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
process_client(request, request.user, is_browser_view=True, process_client(request, request.user, is_browser_view=True,
query=view_func.__name__) query=view_func.__name__)
return rate_limit()(view_func)(request, *args, **kwargs) return rate_limit()(view_func)(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def human_users_only(view_func: ViewFuncT) -> ViewFuncT: def human_users_only(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
if request.user.is_bot: if request.user.is_bot:
return json_error(_("This endpoint does not accept bot requests.")) return json_error(_("This endpoint does not accept bot requests."))
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
# Based on Django 1.8's @login_required # Based on Django 1.8's @login_required
def zulip_login_required( def zulip_login_required(
@ -478,54 +478,54 @@ def zulip_login_required(
def require_server_admin(view_func: ViewFuncT) -> ViewFuncT: def require_server_admin(view_func: ViewFuncT) -> ViewFuncT:
@zulip_login_required @zulip_login_required
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
if not request.user.is_staff: if not request.user.is_staff:
return HttpResponseRedirect(settings.HOME_NOT_LOGGED_IN) return HttpResponseRedirect(settings.HOME_NOT_LOGGED_IN)
return add_logging_data(view_func)(request, *args, **kwargs) return add_logging_data(view_func)(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def require_server_admin_api(view_func: ViewFuncT) -> ViewFuncT: def require_server_admin_api(view_func: ViewFuncT) -> ViewFuncT:
@zulip_login_required @zulip_login_required
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, *args: Any, def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, *args: object,
**kwargs: Any) -> HttpResponse: **kwargs: object) -> HttpResponse:
if not user_profile.is_staff: if not user_profile.is_staff:
raise JsonableError(_("Must be an server administrator")) raise JsonableError(_("Must be an server administrator"))
return view_func(request, user_profile, *args, **kwargs) return view_func(request, user_profile, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def require_non_guest_user(view_func: ViewFuncT) -> ViewFuncT: def require_non_guest_user(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, *args: Any, def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, *args: object,
**kwargs: Any) -> HttpResponse: **kwargs: object) -> HttpResponse:
if user_profile.is_guest: if user_profile.is_guest:
raise JsonableError(_("Not allowed for guest users")) raise JsonableError(_("Not allowed for guest users"))
return view_func(request, user_profile, *args, **kwargs) return view_func(request, user_profile, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def require_member_or_admin(view_func: ViewFuncT) -> ViewFuncT: def require_member_or_admin(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, *args: Any, def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, *args: object,
**kwargs: Any) -> HttpResponse: **kwargs: object) -> HttpResponse:
if user_profile.is_guest: if user_profile.is_guest:
raise JsonableError(_("Not allowed for guest users")) raise JsonableError(_("Not allowed for guest users"))
if user_profile.is_bot: if user_profile.is_bot:
return json_error(_("This endpoint does not accept bot requests.")) return json_error(_("This endpoint does not accept bot requests."))
return view_func(request, user_profile, *args, **kwargs) return view_func(request, user_profile, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def require_user_group_edit_permission(view_func: ViewFuncT) -> ViewFuncT: def require_user_group_edit_permission(view_func: ViewFuncT) -> ViewFuncT:
@require_member_or_admin @require_member_or_admin
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile, def _wrapped_view_func(request: HttpRequest, user_profile: UserProfile,
*args: Any, **kwargs: Any) -> HttpResponse: *args: object, **kwargs: object) -> HttpResponse:
realm = user_profile.realm realm = user_profile.realm
if realm.user_group_edit_policy != Realm.USER_GROUP_EDIT_POLICY_MEMBERS and \ if realm.user_group_edit_policy != Realm.USER_GROUP_EDIT_POLICY_MEMBERS and \
not user_profile.is_realm_admin: not user_profile.is_realm_admin:
raise OrganizationAdministratorRequired() raise OrganizationAdministratorRequired()
return view_func(request, user_profile, *args, **kwargs) return view_func(request, user_profile, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
# This API endpoint is used only for the mobile apps. It is part of a # This API endpoint is used only for the mobile apps. It is part of a
# workaround for the fact that React Native doesn't support setting # workaround for the fact that React Native doesn't support setting
@ -539,7 +539,7 @@ def authenticated_uploads_api_view(
@wraps(view_func) @wraps(view_func)
def _wrapped_func_arguments(request: HttpRequest, def _wrapped_func_arguments(request: HttpRequest,
api_key: str=REQ(), api_key: str=REQ(),
*args: Any, **kwargs: Any) -> HttpResponse: *args: object, **kwargs: object) -> HttpResponse:
user_profile = validate_api_key(request, None, api_key, False) user_profile = validate_api_key(request, None, api_key, False)
if not skip_rate_limiting: if not skip_rate_limiting:
limited_func = rate_limit()(view_func) limited_func = rate_limit()(view_func)
@ -563,7 +563,7 @@ def authenticated_rest_api_view(
def _wrapped_view_func(view_func: Callable[..., HttpResponse]) -> Callable[..., HttpResponse]: def _wrapped_view_func(view_func: Callable[..., HttpResponse]) -> Callable[..., HttpResponse]:
@csrf_exempt @csrf_exempt
@wraps(view_func) @wraps(view_func)
def _wrapped_func_arguments(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_func_arguments(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
# First try block attempts to get the credentials we need to do authentication # First try block attempts to get the credentials we need to do authentication
try: try:
# Grab the base64-encoded authentication string, decode it, and split it into # Grab the base64-encoded authentication string, decode it, and split it into
@ -597,15 +597,12 @@ def authenticated_rest_api_view(
if is_webhook or webhook_client_name is not None: if is_webhook or webhook_client_name is not None:
request_body = request.POST.get('payload') request_body = request.POST.get('payload')
if request_body is not None: if request_body is not None:
kwargs = { log_exception_to_webhook_logger(
'request_body': request_body, request_body=request_body,
'request': request, request=request,
'user_profile': profile, user_profile=profile,
} unexpected_event=isinstance(err, UnexpectedWebhookEventType),
if isinstance(err, UnexpectedWebhookEventType): )
kwargs['unexpected_event'] = True
log_exception_to_webhook_logger(**kwargs)
raise err raise err
return _wrapped_func_arguments return _wrapped_func_arguments
@ -613,7 +610,7 @@ def authenticated_rest_api_view(
def process_as_post(view_func: ViewFuncT) -> ViewFuncT: def process_as_post(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
# Adapted from django/http/__init__.py. # Adapted from django/http/__init__.py.
# So by default Django doesn't populate request.POST for anything besides # So by default Django doesn't populate request.POST for anything besides
# POST requests. We want this dict populated for PATCH/PUT, so we have to # POST requests. We want this dict populated for PATCH/PUT, so we have to
@ -639,13 +636,16 @@ def process_as_post(view_func: ViewFuncT) -> ViewFuncT:
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def authenticate_log_and_execute_json(request: HttpRequest, def authenticate_log_and_execute_json(
view_func: ViewFuncT, request: HttpRequest,
*args: Any, skip_rate_limiting: bool = False, view_func: ViewFuncT,
allow_unauthenticated: bool=False, *args: object,
**kwargs: Any) -> HttpResponse: skip_rate_limiting: bool = False,
allow_unauthenticated: bool = False,
**kwargs: object,
) -> HttpResponse:
if not skip_rate_limiting: if not skip_rate_limiting:
limited_view_func = rate_limit()(view_func) limited_view_func = rate_limit()(view_func)
else: else:
@ -680,10 +680,15 @@ def authenticated_json_view(
) -> Callable[..., HttpResponse]: ) -> Callable[..., HttpResponse]:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, def _wrapped_view_func(request: HttpRequest,
*args: Any, **kwargs: Any) -> HttpResponse: *args: object, **kwargs: object) -> HttpResponse:
kwargs["skip_rate_limiting"] = skip_rate_limiting return authenticate_log_and_execute_json(
kwargs["allow_unauthenticated"] = allow_unauthenticated request,
return authenticate_log_and_execute_json(request, view_func, *args, **kwargs) view_func,
*args,
skip_rate_limiting=skip_rate_limiting,
allow_unauthenticated=allow_unauthenticated,
**kwargs,
)
return _wrapped_view_func return _wrapped_view_func
def is_local_addr(addr: str) -> bool: def is_local_addr(addr: str) -> bool:
@ -714,7 +719,7 @@ def internal_notify_view(is_tornado_view: bool) -> Callable[[ViewFuncT], ViewFun
@csrf_exempt @csrf_exempt
@require_post @require_post
@wraps(view_func) @wraps(view_func)
def _wrapped_func_arguments(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_func_arguments(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
if not authenticate_notify(request): if not authenticate_notify(request):
return json_error(_('Access denied'), status=403) return json_error(_('Access denied'), status=403)
is_tornado_request = hasattr(request, '_tornado_handler') is_tornado_request = hasattr(request, '_tornado_handler')
@ -760,7 +765,7 @@ def rate_limit(domain: str='api_by_user') -> Callable[[ViewFuncT], ViewFuncT]:
Returns a decorator""" Returns a decorator"""
def wrapper(func: ViewFuncT) -> ViewFuncT: def wrapper(func: ViewFuncT) -> ViewFuncT:
@wraps(func) @wraps(func)
def wrapped_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def wrapped_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
# It is really tempting to not even wrap our original function # It is really tempting to not even wrap our original function
# when settings.RATE_LIMITING is False, but it would make # when settings.RATE_LIMITING is False, but it would make
@ -794,16 +799,16 @@ def rate_limit(domain: str='api_by_user') -> Callable[[ViewFuncT], ViewFuncT]:
rate_limit_user(request, user, domain) rate_limit_user(request, user, domain)
return func(request, *args, **kwargs) return func(request, *args, **kwargs)
return wrapped_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapped_func) # https://github.com/python/mypy/issues/1927
return wrapper return wrapper
def return_success_on_head_request(view_func: ViewFuncT) -> ViewFuncT: def return_success_on_head_request(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
if request.method == 'HEAD': if request.method == 'HEAD':
return json_success() return json_success()
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
def zulip_otp_required( def zulip_otp_required(
redirect_field_name: str='next', redirect_field_name: str='next',
@ -839,13 +844,15 @@ def zulip_otp_required(
return decorator return decorator
def add_google_analytics_context(context: Dict[str, Any]) -> None: def add_google_analytics_context(context: Dict[str, object]) -> None:
if settings.GOOGLE_ANALYTICS_ID is not None: # nocoverage if settings.GOOGLE_ANALYTICS_ID is not None: # nocoverage
context.setdefault("page_params", {})["google_analytics_id"] = settings.GOOGLE_ANALYTICS_ID page_params = context.setdefault("page_params", {})
assert isinstance(page_params, dict)
page_params["google_analytics_id"] = settings.GOOGLE_ANALYTICS_ID
def add_google_analytics(view_func: ViewFuncT) -> ViewFuncT: def add_google_analytics(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
response = view_func(request, *args, **kwargs) response = view_func(request, *args, **kwargs)
if isinstance(response, SimpleTemplateResponse): if isinstance(response, SimpleTemplateResponse):
if response.context_data is None: if response.context_data is None:
@ -854,4 +861,4 @@ def add_google_analytics(view_func: ViewFuncT) -> ViewFuncT:
elif response.status_code == 200: # nocoverage elif response.status_code == 200: # nocoverage
raise TypeError("add_google_analytics requires a TemplateResponse") raise TypeError("add_google_analytics requires a TemplateResponse")
return response return response
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927

View File

@ -283,7 +283,7 @@ def has_request_variables(view_func: ViewFuncT) -> ViewFuncT:
arguments_map[view_func_full_name].append(value.post_var_name) arguments_map[view_func_full_name].append(value.post_var_name)
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
for param in post_params: for param in post_params:
func_var_name = param.func_var_name func_var_name = param.func_var_name
if param.path_only: if param.path_only:
@ -369,4 +369,4 @@ def has_request_variables(view_func: ViewFuncT) -> ViewFuncT:
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
return cast(ViewFuncT, _wrapped_view_func) return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927

View File

@ -1,6 +1,6 @@
import functools import functools
import sys import sys
from typing import IO, Any, Callable, Mapping, Sequence, TypeVar from typing import IO, Any, Callable, Mapping, Sequence, TypeVar, cast
def get_mapping_type_str(x: Mapping[Any, Any]) -> str: def get_mapping_type_str(x: Mapping[Any, Any]) -> str:
@ -63,12 +63,12 @@ def get_type_str(x: Any) -> str:
else: else:
return type(x).__name__ return type(x).__name__
FuncT = TypeVar('FuncT', bound=Callable[..., Any]) FuncT = TypeVar('FuncT', bound=Callable[..., object])
def print_types_to(file_obj: IO[str]) -> Callable[[FuncT], FuncT]: def print_types_to(file_obj: IO[str]) -> Callable[[FuncT], FuncT]:
def decorator(func: FuncT) -> FuncT: def decorator(func: FuncT) -> FuncT:
@functools.wraps(func) @functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any: def wrapper(*args: object, **kwargs: object) -> object:
arg_types = [get_type_str(arg) for arg in args] arg_types = [get_type_str(arg) for arg in args]
kwarg_types = [key + "=" + get_type_str(value) for key, value in kwargs.items()] kwarg_types = [key + "=" + get_type_str(value) for key, value in kwargs.items()]
ret_val = func(*args, **kwargs) ret_val = func(*args, **kwargs)
@ -77,7 +77,7 @@ def print_types_to(file_obj: IO[str]) -> Callable[[FuncT], FuncT]:
get_type_str(ret_val)) get_type_str(ret_val))
print(output, file=file_obj) print(output, file=file_obj)
return ret_val return ret_val
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(FuncT, wrapper) # https://github.com/python/mypy/issues/1927
return decorator return decorator
def print_types(func: FuncT) -> FuncT: def print_types(func: FuncT) -> FuncT:

View File

@ -2,7 +2,7 @@ import logging
import sys import sys
from functools import wraps from functools import wraps
from types import TracebackType from types import TracebackType
from typing import Any, Callable, Dict, Iterator, NoReturn, Optional, Tuple, Type from typing import Callable, Dict, Iterator, NoReturn, Optional, Tuple, Type, cast
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from django.conf import settings from django.conf import settings
@ -20,7 +20,7 @@ captured_exc_info: Tuple[Optional[Type[BaseException]], Optional[BaseException],
def capture_and_throw(domain: Optional[str]=None) -> Callable[[ViewFuncT], ViewFuncT]: def capture_and_throw(domain: Optional[str]=None) -> Callable[[ViewFuncT], ViewFuncT]:
def wrapper(view_func: ViewFuncT) -> ViewFuncT: def wrapper(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def wrapped_view(request: HttpRequest, *args: Any, **kwargs: Any) -> NoReturn: def wrapped_view(request: HttpRequest, *args: object, **kwargs: object) -> NoReturn:
global captured_request global captured_request
captured_request = request captured_request = request
try: try:
@ -29,7 +29,7 @@ def capture_and_throw(domain: Optional[str]=None) -> Callable[[ViewFuncT], ViewF
global captured_exc_info global captured_exc_info
captured_exc_info = sys.exc_info() captured_exc_info = sys.exc_info()
raise e raise e
return wrapped_view # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapped_view) # https://github.com/python/mypy/issues/1927
return wrapper return wrapper
class AdminNotifyHandlerTest(ZulipTestCase): class AdminNotifyHandlerTest(ZulipTestCase):
@ -90,7 +90,7 @@ class AdminNotifyHandlerTest(ZulipTestCase):
) )
return record return record
def run_handler(self, record: logging.LogRecord) -> Dict[str, Any]: def run_handler(self, record: logging.LogRecord) -> Dict[str, object]:
with patch('zerver.lib.error_notify.notify_server_error') as patched_notify: with patch('zerver.lib.error_notify.notify_server_error') as patched_notify:
self.handler.emit(record) self.handler.emit(record)
patched_notify.assert_called_once() patched_notify.assert_called_once()

View File

@ -2,7 +2,7 @@ import logging
import os import os
import urllib import urllib
from functools import wraps from functools import wraps
from typing import Any, Dict, List, Mapping, Optional from typing import Any, Dict, List, Mapping, Optional, cast
import jwt import jwt
from cryptography.hazmat.primitives.ciphers.aead import AESGCM from cryptography.hazmat.primitives.ciphers.aead import AESGCM
@ -479,13 +479,13 @@ def oauth_redirect_to_root(
def handle_desktop_flow(func: ViewFuncT) -> ViewFuncT: def handle_desktop_flow(func: ViewFuncT) -> ViewFuncT:
@wraps(func) @wraps(func)
def wrapper(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def wrapper(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
user_agent = parse_user_agent(request.META.get("HTTP_USER_AGENT", "Missing User-Agent")) user_agent = parse_user_agent(request.META.get("HTTP_USER_AGENT", "Missing User-Agent"))
if user_agent["name"] == "ZulipElectron": if user_agent["name"] == "ZulipElectron":
return render(request, "zerver/desktop_login.html") return render(request, "zerver/desktop_login.html")
return func(request, *args, **kwargs) return func(request, *args, **kwargs)
return wrapper # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, wrapper) # https://github.com/python/mypy/issues/1927
@handle_desktop_flow @handle_desktop_flow
def start_remote_user_sso(request: HttpRequest) -> HttpResponse: def start_remote_user_sso(request: HttpRequest) -> HttpResponse:

View File

@ -2,7 +2,7 @@
import base64 import base64
import re import re
from functools import wraps from functools import wraps
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple, cast
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
@ -45,7 +45,7 @@ def _transform_commits_list_to_common_format(commits: List[Dict[str, Any]]) -> L
# We manually fix the username here before passing it along to @authenticated_rest_api_view # We manually fix the username here before passing it along to @authenticated_rest_api_view
def beanstalk_decoder(view_func: ViewFuncT) -> ViewFuncT: def beanstalk_decoder(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
auth_type: str auth_type: str
encoded_value: str encoded_value: str
auth_type, encoded_value = request.META['HTTP_AUTHORIZATION'].split() auth_type, encoded_value = request.META['HTTP_AUTHORIZATION'].split()
@ -58,7 +58,7 @@ def beanstalk_decoder(view_func: ViewFuncT) -> ViewFuncT:
return view_func(request, *args, **kwargs) return view_func(request, *args, **kwargs)
return _wrapped_view_func # type: ignore[return-value] # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
@beanstalk_decoder @beanstalk_decoder
@authenticated_rest_api_view(webhook_client_name="Beanstalk") @authenticated_rest_api_view(webhook_client_name="Beanstalk")