request: Refactor ZulipRequestNotes to RequestNotes.

This utilizes the generic `BaseNotes` we added for multipurpose
patching. With this migration as an example, we can further support
more types of notes to replace the monkey-patching approach we have used
throughout the codebase for type safety.
This commit is contained in:
PIG208 2021-08-22 01:24:20 +08:00 committed by Tim Abbott
parent dba7b1e3a7
commit 53888e5a26
32 changed files with 124 additions and 124 deletions

View File

@ -17,7 +17,7 @@ from version import (
from zerver.lib.exceptions import InvalidSubdomainError
from zerver.lib.realm_description import get_realm_rendered_description, get_realm_text_description
from zerver.lib.realm_icon import get_realm_icon_url
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.lib.send_email import FromAddress
from zerver.lib.subdomains import get_subdomain
from zerver.models import Realm, UserProfile, get_realm
@ -50,7 +50,7 @@ def common_context(user: UserProfile) -> Dict[str, Any]:
def get_realm_from_request(request: HttpRequest) -> Optional[Realm]:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if hasattr(request, "user") and hasattr(request.user, "realm"):
return request.user.realm
if not request_notes.has_fetched_realm:
@ -59,7 +59,7 @@ def get_realm_from_request(request: HttpRequest) -> Optional[Realm]:
# need to do duplicate queries on the same realm while
# processing a single request.
subdomain = get_subdomain(request)
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
try:
request_notes.realm = get_realm(subdomain)
except Realm.DoesNotExist:
@ -169,7 +169,7 @@ def zulip_default_context(request: HttpRequest) -> Dict[str, Any]:
"settings_path": settings_path,
"secrets_path": secrets_path,
"settings_comments_path": settings_comments_path,
"platform": get_request_notes(request).client_name,
"platform": RequestNotes.get_notes(request).client_name,
"allow_search_engine_indexing": allow_search_engine_indexing,
"landing_page_navbar_message": settings.LANDING_PAGE_NAVBAR_MESSAGE,
"default_page_params": default_page_params,

View File

@ -40,7 +40,7 @@ from zerver.lib.exceptions import (
)
from zerver.lib.queue import queue_json_publish
from zerver.lib.rate_limiter import RateLimitedIPAddr, RateLimitedUser
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_method_not_allowed, json_success, json_unauthorized
from zerver.lib.subdomains import get_subdomain, user_matches_subdomain
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
@ -85,7 +85,7 @@ def update_user_activity(
if request.META["PATH_INFO"] == "/json/users/me/presence":
return
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if query is not None:
pass
elif request_notes.query is not None:
@ -115,7 +115,7 @@ def require_post(func: ViewFuncT) -> ViewFuncT:
request.path,
extra={"status_code": 405, "request": request},
)
if get_request_notes(request).error_format == "JSON":
if RequestNotes.get_notes(request).error_format == "JSON":
return json_method_not_allowed(["POST"])
else:
return TemplateResponse(
@ -183,7 +183,7 @@ def process_client(
skip_update_user_activity: bool = False,
query: Optional[str] = None,
) -> None:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if client_name is None:
client_name = request_notes.client_name
@ -438,7 +438,7 @@ def do_login(request: HttpRequest, user_profile: UserProfile) -> None:
and also adds helpful data needed by our server logs.
"""
django_login(request, user_profile)
get_request_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
RequestNotes.get_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
process_client(request, user_profile, is_browser_view=True)
if settings.TWO_FACTOR_AUTHENTICATION_ENABLED:
# Log in with two factor authentication as well.
@ -448,7 +448,7 @@ def do_login(request: HttpRequest, user_profile: UserProfile) -> None:
def log_view_func(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
get_request_notes(request).query = view_func.__name__
RequestNotes.get_notes(request).query = view_func.__name__
return view_func(request, *args, **kwargs)
return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927
@ -808,7 +808,7 @@ def client_is_exempt_from_rate_limiting(request: HttpRequest) -> bool:
# Don't rate limit requests from Django that come from our own servers,
# and don't rate-limit dev instances
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
return (client is not None and client.name.lower() == "internal") and (
is_local_addr(request.META["REMOTE_ADDR"]) or settings.DEBUG_RATE_LIMITING
)
@ -832,7 +832,7 @@ def internal_notify_view(
) -> HttpResponse:
if not authenticate_notify(request):
raise AccessDeniedError()
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
is_tornado_request = request_notes.tornado_handler is not None
# These next 2 are not security checks; they are internal
# assertions to help us find bugs.

View File

@ -15,7 +15,7 @@ from zerver.lib.i18n import (
get_language_list,
get_language_translation_data,
)
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.models import Message, Realm, Stream, UserProfile
from zerver.views.message_flags import get_latest_update_message_flag_activity
@ -139,7 +139,7 @@ def build_page_params_for_home_page_load(
}
if user_profile is not None:
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
register_ret = do_events_register(
user_profile,

View File

@ -10,7 +10,7 @@ from django.conf import settings
from django.http import HttpRequest
from django.utils import translation
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
@lru_cache()
@ -64,6 +64,6 @@ def get_and_set_request_language(
# something reasonable will happen in logged-in portico pages.
# We accomplish that by setting a flag on the request which signals
# to LocaleMiddleware to set the cookie on the response.
get_request_notes(request).set_language = translation.get_language()
RequestNotes.get_notes(request).set_language = translation.get_language()
return request_language

View File

@ -276,9 +276,9 @@ class ZulipWebhookFormatter(ZulipFormatter):
)
header_message = header_text if header_text else None
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
setattr(record, "user", f"{request.user.delivery_email} ({request.user.realm.string_id})")

View File

@ -42,10 +42,10 @@ class RateLimitedObject(ABC):
)
def rate_limit_request(self, request: HttpRequest) -> None:
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
ratelimited, time = self.rate_limit()
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
request_notes.ratelimits_applied.append(
RateLimitResult(

View File

@ -29,19 +29,21 @@ from typing_extensions import Literal
import zerver.lib.rate_limiter as rate_limiter
import zerver.tornado.handlers as handlers
from zerver.lib.exceptions import ErrorCode, InvalidJSONError, JsonableError
from zerver.lib.notes import BaseNotes
from zerver.lib.types import Validator, ViewFuncT
from zerver.models import Client, Realm
@dataclass
class ZulipRequestNotes:
class RequestNotes(BaseNotes[HttpRequest, "RequestNotes"]):
"""This class contains extra metadata that Zulip associated with a
Django HttpRequest object.
Django HttpRequest object. See the docstring for BaseNotes for
details on how it works.
Note that most Optional fields will be definitely not None once
middlware has run. In the future, we may want to express that in
the types by having different types ZulipEarlyRequestNotes and
post-middleware ZulipRequestNotes types, but for now we have a lot
the types by having different types EarlyRequestNotes and
post-middleware RequestNotes types, but for now we have a lot
of `assert request_notes.foo is not None` when accessing them.
"""
@ -68,16 +70,9 @@ class ZulipRequestNotes:
processed_parameters: Set[str] = field(default_factory=set)
ignored_parameters: Set[str] = field(default_factory=set)
request_notes_map: MutableMapping[HttpRequest, ZulipRequestNotes] = weakref.WeakKeyDictionary()
def get_request_notes(request: HttpRequest) -> ZulipRequestNotes:
try:
return request_notes_map[request]
except KeyError:
request_notes_map[request] = ZulipRequestNotes()
return request_notes_map[request]
@classmethod
def init_notes(cls) -> "RequestNotes":
return RequestNotes()
class RequestConfusingParmsError(JsonableError):
@ -358,7 +353,7 @@ def has_request_variables(view_func: ViewFuncT) -> ViewFuncT:
@wraps(view_func)
def _wrapped_view_func(request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
for param in post_params:
func_var_name = param.func_var_name
if param.path_only:

View File

@ -14,7 +14,7 @@ from zerver.decorator import (
process_as_post,
)
from zerver.lib.exceptions import MissingAuthenticationError
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.lib.response import json_method_not_allowed
from zerver.lib.types import ViewFuncT
@ -66,7 +66,7 @@ def rest_dispatch(request: HttpRequest, **kwargs: Any) -> HttpResponse:
etc, as that is where we route HTTP verbs to target functions.
"""
supported_methods: Dict[str, Any] = {}
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if request_notes.saved_response is not None:
# For completing long-polled Tornado requests, we skip the
# view function logic and just return the response.

View File

@ -45,7 +45,8 @@ from zerver.lib.avatar import avatar_url
from zerver.lib.cache import get_cache_backend
from zerver.lib.db import Params, ParamsT, Query, TimeTrackingCursor
from zerver.lib.integrations import WEBHOOK_INTEGRATIONS
from zerver.lib.request import ZulipRequestNotes, request_notes_map
from zerver.lib.notes import BaseNotes
from zerver.lib.request import RequestNotes
from zerver.lib.upload import LocalUploadBackend, S3UploadBackend
from zerver.models import (
Client,
@ -320,12 +321,16 @@ class HostRequestMock(HttpRequest):
self.user = user_profile
self._body = b""
self.content_type = ""
BaseNotes[str, str].get_notes
request_notes_map[self] = ZulipRequestNotes(
client_name="",
log_data={},
tornado_handler=None if tornado_handler is None else weakref.ref(tornado_handler),
client=get_client(client_name) if client_name is not None else None,
RequestNotes.set_notes(
self,
RequestNotes(
client_name="",
log_data={},
tornado_handler=None if tornado_handler is None else weakref.ref(tornado_handler),
client=get_client(client_name) if client_name is not None else None,
),
)
@property

View File

@ -14,7 +14,7 @@ from zerver.lib.actions import (
send_rate_limited_pm_notification_to_bot_owner,
)
from zerver.lib.exceptions import ErrorCode, JsonableError, StreamDoesNotExistError
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.send_email import FromAddress
from zerver.lib.timestamp import timestamp_to_datetime
from zerver.lib.validator import check_list, check_string
@ -107,7 +107,7 @@ def check_send_webhook_message(
):
return
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
if stream is None:
assert user_profile.bot_owner is not None

View File

@ -38,7 +38,7 @@ from zerver.lib.exceptions import ErrorCode, JsonableError, MissingAuthenticatio
from zerver.lib.html_to_text import get_content_description
from zerver.lib.markdown import get_markdown_requests, get_markdown_time
from zerver.lib.rate_limiter import RateLimitResult
from zerver.lib.request import get_request_notes, set_request, unset_request
from zerver.lib.request import RequestNotes, set_request, unset_request
from zerver.lib.response import json_response, json_response_from_error, json_unauthorized
from zerver.lib.subdomains import get_subdomain
from zerver.lib.types import ViewFuncT
@ -61,7 +61,7 @@ def record_request_stop_data(log_data: MutableMapping[str, Any]) -> None:
def async_request_timer_stop(request: HttpRequest) -> None:
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
record_request_stop_data(log_data)
@ -77,7 +77,7 @@ def record_request_restart_data(log_data: MutableMapping[str, Any]) -> None:
def async_request_timer_restart(request: HttpRequest) -> None:
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
if "time_restarted" in log_data:
# Don't destroy data when being called from
@ -341,7 +341,7 @@ class LogRequests(MiddlewareMixin):
# method here too
def process_request(self, request: HttpRequest) -> None:
maybe_tracemalloc_listen()
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if request_notes.log_data is not None:
# Sanity check to ensure this is being called from the
@ -362,7 +362,7 @@ class LogRequests(MiddlewareMixin):
args: List[str],
kwargs: Dict[str, Any],
) -> None:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if request_notes.saved_response is not None:
# The below logging adjustments are unnecessary (because
# we've already imported everything) and incorrect
@ -394,7 +394,7 @@ class LogRequests(MiddlewareMixin):
remote_ip = request.META["REMOTE_ADDR"]
# Get the requestor's identifier and client, if available.
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
requestor_for_logs = request_notes.requestor_for_logs
if requestor_for_logs is None:
# Note that request.user is a Union[RemoteZulipServer, UserProfile, AnonymousUser],
@ -455,7 +455,7 @@ class JsonErrorHandler(MiddlewareMixin):
if isinstance(exception, JsonableError):
return json_response_from_error(exception)
if get_request_notes(request).error_format == "JSON":
if RequestNotes.get_notes(request).error_format == "JSON":
capture_exception(exception)
json_error_logger = logging.getLogger("zerver.middleware.json_error_handler")
json_error_logger.error(traceback.format_exc(), extra=dict(request=request))
@ -471,9 +471,9 @@ class TagRequests(MiddlewareMixin):
def process_request(self, request: HttpRequest) -> None:
if request.path.startswith("/api/") or request.path.startswith("/json/"):
get_request_notes(request).error_format = "JSON"
RequestNotes.get_notes(request).error_format = "JSON"
else:
get_request_notes(request).error_format = "HTML"
RequestNotes.get_notes(request).error_format = "HTML"
class CsrfFailureError(JsonableError):
@ -490,7 +490,7 @@ class CsrfFailureError(JsonableError):
def csrf_failure(request: HttpRequest, reason: str = "") -> HttpResponse:
if get_request_notes(request).error_format == "JSON":
if RequestNotes.get_notes(request).error_format == "JSON":
return json_response_from_error(CsrfFailureError(reason))
else:
return html_csrf_failure(request, reason)
@ -517,7 +517,7 @@ class LocaleMiddleware(DjangoLocaleMiddleware):
# An additional responsibility of our override of this middleware is to save the user's language
# preference in a cookie. That determination is made by code handling the request
# and saved in the set_language flag so that it can be used here.
set_language = get_request_notes(request).set_language
set_language = RequestNotes.get_notes(request).set_language
if set_language is not None:
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, set_language)
@ -544,7 +544,7 @@ class RateLimitMiddleware(MiddlewareMixin):
return response
# Add X-RateLimit-*** headers
ratelimits_applied = get_request_notes(request).ratelimits_applied
ratelimits_applied = RequestNotes.get_notes(request).ratelimits_applied
if len(ratelimits_applied) > 0:
self.set_response_headers(response, ratelimits_applied)
@ -577,7 +577,7 @@ class HostDomainMiddleware(MiddlewareMixin):
subdomain = get_subdomain(request)
if subdomain != Realm.SUBDOMAIN_FOR_ROOT_DOMAIN:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
try:
request_notes.realm = get_realm(subdomain)
except Realm.DoesNotExist:
@ -614,7 +614,7 @@ class SetRemoteAddrFromRealIpHeader(MiddlewareMixin):
def alter_content(request: HttpRequest, content: bytes) -> bytes:
first_paragraph_text = get_content_description(content, request)
placeholder_open_graph_description = get_request_notes(
placeholder_open_graph_description = RequestNotes.get_notes(
request
).placeholder_open_graph_description
assert placeholder_open_graph_description is not None
@ -629,7 +629,7 @@ class FinalizeOpenGraphDescription(MiddlewareMixin):
self, request: HttpRequest, response: StreamingHttpResponse
) -> StreamingHttpResponse:
if get_request_notes(request).placeholder_open_graph_description is not None:
if RequestNotes.get_notes(request).placeholder_open_graph_description is not None:
assert not response.streaming
response.content = alter_content(request, response.content)
return response

View File

@ -47,9 +47,9 @@ from zerver.lib.initial_password import initial_password
from zerver.lib.request import (
REQ,
RequestConfusingParmsError,
RequestNotes,
RequestVariableConversionError,
RequestVariableMissingError,
get_request_notes,
has_request_variables,
)
from zerver.lib.response import json_response, json_success
@ -1428,19 +1428,19 @@ class TestInternalNotifyView(ZulipTestCase):
orjson.loads(self.internal_notify(False, request).content).get("msg"),
self.BORING_RESULT,
)
self.assertEqual(get_request_notes(request).requestor_for_logs, "internal")
self.assertEqual(RequestNotes.get_notes(request).requestor_for_logs, "internal")
with self.assertRaises(RuntimeError):
self.internal_notify(True, request)
get_request_notes(request).tornado_handler = DummyHandler()
RequestNotes.get_notes(request).tornado_handler = DummyHandler()
with self.settings(SHARED_SECRET=secret):
self.assertTrue(authenticate_notify(request))
self.assertEqual(
orjson.loads(self.internal_notify(True, request).content).get("msg"),
self.BORING_RESULT,
)
self.assertEqual(get_request_notes(request).requestor_for_logs, "internal")
self.assertEqual(RequestNotes.get_notes(request).requestor_for_logs, "internal")
with self.assertRaises(RuntimeError):
self.internal_notify(False, request)

View File

@ -47,7 +47,7 @@ def finish_handler(
try:
# We do the import during runtime to avoid cyclic dependency
# with zerver.lib.request
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.middleware import async_request_timer_restart
# We call async_request_timer_restart here in case we are
@ -56,7 +56,7 @@ def finish_handler(
handler = get_handler_by_id(handler_id)
request = handler._request
async_request_timer_restart(request)
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
if len(contents) != 1:
log_data["extra"] = f"[{event_queue_id}/1]"
@ -113,11 +113,11 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
request = WSGIRequest(environ)
# We do the import during runtime to avoid cyclic dependency
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
# Provide a way for application code to access this handler
# given the HttpRequest object.
get_request_notes(request).tornado_handler = weakref.ref(self)
RequestNotes.get_notes(request).tornado_handler = weakref.ref(self)
return request
@ -228,12 +228,12 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
# HttpResponse with all Django middleware run.
request = self.convert_tornado_request_to_django_request()
# We import get_request_notes during runtime to avoid
# We import RequestNotes during runtime to avoid
# cyclic import
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
request_notes = get_request_notes(request)
old_request_notes = get_request_notes(old_request)
request_notes = RequestNotes.get_notes(request)
old_request_notes = RequestNotes.get_notes(old_request)
# Add to this new HttpRequest logging data from the processing of
# the original request; we will need these for logging.

View File

@ -7,7 +7,7 @@ from django.utils.translation import gettext as _
from zerver.decorator import internal_notify_view, process_client
from zerver.lib.exceptions import JsonableError
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.validator import (
check_bool,
@ -36,7 +36,7 @@ def cleanup_event_queue(
raise BadEventQueueIdError(queue_id)
if user_profile.id != client.user_profile_id:
raise JsonableError(_("You are not authorized to access this queue"))
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = f"[{queue_id}]"
client.cleanup()
@ -49,7 +49,7 @@ def get_events_internal(
request: HttpRequest, user_profile_id: int = REQ(json_validator=check_int)
) -> HttpResponse:
user_profile = get_user_profile_by_id(user_profile_id)
get_request_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
RequestNotes.get_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
process_client(request, user_profile, client_name="internal")
return get_events_backend(request, user_profile)
@ -111,13 +111,13 @@ def get_events_backend(
raise JsonableError(_("User not authorized for this query"))
# Extract the Tornado handler from the request
tornado_handler = get_request_notes(request).tornado_handler
tornado_handler = RequestNotes.get_notes(request).tornado_handler
assert tornado_handler is not None
handler = tornado_handler()
assert handler is not None
if user_client is None:
valid_user_client = get_request_notes(request).client
valid_user_client = RequestNotes.get_notes(request).client
assert valid_user_client is not None
else:
valid_user_client = user_client
@ -155,7 +155,7 @@ def get_events_backend(
result = fetch_events(events_query)
if "extra_log_data" in result:
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = result["extra_log_data"]

View File

@ -54,7 +54,7 @@ from zerver.lib.mobile_auth_otp import otp_encrypt_api_key
from zerver.lib.push_notifications import push_notifications_enabled
from zerver.lib.pysa import mark_sanitized
from zerver.lib.realm_icon import realm_icon_url
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.sessions import set_expirable_session_var
from zerver.lib.subdomains import get_subdomain, is_subdomain_root_or_alias
@ -358,7 +358,7 @@ def finish_mobile_flow(request: HttpRequest, user_profile: UserProfile, otp: str
# Mark this request as having a logged-in user for our server logs.
process_client(request, user_profile)
get_request_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
RequestNotes.get_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
return response
@ -866,7 +866,7 @@ def api_fetch_api_key(
# Mark this request as having a logged-in user for our server logs.
process_client(request, user_profile)
get_request_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
RequestNotes.get_notes(request).requestor_for_logs = user_profile.format_requestor_for_logs()
api_key = get_api_key(user_profile)
return json_success({"api_key": api_key, "email": user_profile.delivery_email})

View File

@ -13,7 +13,7 @@ from django.views.generic import TemplateView
from zerver.context_processors import zulip_default_context
from zerver.decorator import add_google_analytics_context
from zerver.lib.integrations import CATEGORIES, INTEGRATIONS, HubotIntegration, WebhookIntegration
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.subdomains import get_subdomain
from zerver.lib.templates import render_markdown_path
from zerver.models import Realm
@ -168,7 +168,7 @@ class MarkdownDirectoryView(ApiURLView):
context["OPEN_GRAPH_TITLE"] = f"{article_title} ({title_base})"
else:
context["OPEN_GRAPH_TITLE"] = title_base
request_notes = get_request_notes(self.request)
request_notes = RequestNotes.get_notes(self.request)
request_notes.placeholder_open_graph_description = (
f"REPLACMENT_OPEN_GRAPH_DESCRIPTION_{int(2**24 * random.random())}"
)

View File

@ -5,7 +5,7 @@ from django.utils.translation import gettext as _
from zerver.lib.events import do_events_register
from zerver.lib.exceptions import JsonableError
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.validator import check_bool, check_dict, check_list, check_string
from zerver.models import Stream, UserProfile
@ -80,7 +80,7 @@ def events_register_backend(
if client_capabilities is None:
client_capabilities = {}
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
ret = do_events_register(

View File

@ -14,7 +14,7 @@ from zerver.forms import ToSForm
from zerver.lib.actions import do_change_tos_version, realm_user_count
from zerver.lib.compatibility import is_outdated_desktop_app, is_unsupported_browser
from zerver.lib.home import build_page_params_for_home_page_load, get_user_permission_info
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.lib.streams import access_stream_by_name
from zerver.lib.subdomains import get_subdomain
from zerver.lib.utils import statsd
@ -192,7 +192,7 @@ def home_real(request: HttpRequest) -> HttpResponse:
needs_tutorial=needs_tutorial,
)
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = f"[{queue_id}]"

View File

@ -11,7 +11,7 @@ from zerver.lib.actions import check_update_message, do_delete_messages
from zerver.lib.exceptions import JsonableError
from zerver.lib.html_diff import highlight_html_differences
from zerver.lib.message import access_message
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.lib.topic import LEGACY_PREV_TOPIC, REQ_topic
@ -117,7 +117,7 @@ def update_message_backend(
)
# Include the number of messages changed in the logs
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = f"[{number_changed}]"

View File

@ -37,7 +37,7 @@ from zerver.lib.addressee import get_user_profiles, get_user_profiles_by_ids
from zerver.lib.exceptions import ErrorCode, JsonableError, MissingAuthenticationError
from zerver.lib.message import get_first_visible_message_id, messages_for_ids
from zerver.lib.narrow import is_web_public_compatible, is_web_public_narrow
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.sqlalchemy_utils import get_sqlalchemy_connection
from zerver.lib.streams import (
@ -1040,7 +1040,7 @@ def get_messages_backend(
verbose_operators.append("is:" + term["operand"])
else:
verbose_operators.append(term["operator"])
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = "[{}]".format(",".join(verbose_operators))

View File

@ -9,7 +9,7 @@ from zerver.lib.actions import (
do_update_message_flags,
)
from zerver.lib.exceptions import JsonableError
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.streams import access_stream_by_id
from zerver.lib.topic import user_message_exists_for_topic
@ -35,7 +35,7 @@ def update_message_flags(
operation: str = REQ("op"),
flag: str = REQ(),
) -> HttpResponse:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
assert request_notes.client is not None
assert request_notes.log_data is not None
@ -50,7 +50,7 @@ def update_message_flags(
@has_request_variables
def mark_all_as_read(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
assert request_notes.client is not None
count = do_mark_all_as_read(user_profile, request_notes.client)
@ -69,7 +69,7 @@ def mark_stream_as_read(
count = do_mark_stream_messages_as_read(user_profile, stream.recipient_id)
log_data_str = f"[{count} updated]"
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = log_data_str
@ -98,7 +98,7 @@ def mark_topic_as_read(
count = do_mark_stream_messages_as_read(user_profile, stream.recipient_id, topic_name)
log_data_str = f"[{count} updated]"
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = log_data_str

View File

@ -19,7 +19,7 @@ from zerver.lib.actions import (
)
from zerver.lib.exceptions import JsonableError
from zerver.lib.message import render_markdown
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.timestamp import convert_to_UTC
from zerver.lib.topic import REQ_topic
@ -53,7 +53,7 @@ def create_mirrored_message_users(
for email in recipients:
referenced_users.add(email.lower())
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
if client.name == "zephyr_mirror":
@ -226,7 +226,7 @@ def send_message_backend(
# `yes` to accepting `true` like all of our normal booleans.
forged = forged_str is not None and forged_str in ["yes", "true"]
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
can_forge_sender = user_profile.can_forge_sender
if forged and not can_forge_sender:
@ -330,7 +330,7 @@ def render_message_backend(
message = Message()
message.sender = user_profile
message.content = content
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
message.sending_client = client

View File

@ -11,7 +11,7 @@ from zerver.lib.actions import do_update_user_status, update_user_presence
from zerver.lib.emoji import check_emoji_request, emoji_name_to_emoji_code
from zerver.lib.exceptions import JsonableError
from zerver.lib.presence import get_presence_for_user, get_presence_response
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.lib.validator import check_bool, check_capped_string
@ -114,7 +114,7 @@ def update_user_status_backend(
assert emoji_type is not None
check_emoji_request(user_profile.realm, emoji_name, emoji_code, emoji_type)
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
do_update_user_status(
user_profile=user_profile,
@ -143,7 +143,7 @@ def update_active_status_backend(
if status_val is None:
raise JsonableError(_("Invalid status: {}").format(status))
elif user_profile.presence_enabled:
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
update_user_presence(user_profile, client, timezone_now(), status_val, new_user_input)

View File

@ -14,7 +14,7 @@ from zerver.context_processors import get_valid_realm_from_request
from zerver.decorator import human_users_only
from zerver.lib.markdown import privacy_clean_markdown
from zerver.lib.queue import queue_json_publish
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.storage import static_path
from zerver.lib.unminify import SourceMap
@ -54,7 +54,7 @@ def report_send_times(
if displayed > 0:
displayed_str = str(displayed)
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data[
"extra"
@ -81,7 +81,7 @@ def report_narrow_times(
initial_free: int = REQ(converter=to_non_negative_int),
network: int = REQ(converter=to_non_negative_int),
) -> HttpResponse:
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = f"[{initial_core}ms/{initial_free}ms/{network}ms]"
realm = get_valid_realm_from_request(request)
@ -99,7 +99,7 @@ def report_unnarrow_times(
initial_core: int = REQ(converter=to_non_negative_int),
initial_free: int = REQ(converter=to_non_negative_int),
) -> HttpResponse:
log_data = get_request_notes(request).log_data
log_data = RequestNotes.get_notes(request).log_data
assert log_data is not None
log_data["extra"] = f"[{initial_core}ms/{initial_free}ms]"
realm = get_valid_realm_from_request(request)

View File

@ -276,9 +276,9 @@ def json_change_settings(
do_set_user_display_setting(user_profile, "timezone", timezone)
# TODO: Do this more generally.
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
for req_var in request.POST:
if req_var not in request_notes.processed_parameters:
request_notes.ignored_parameters.add(req_var)

View File

@ -5,7 +5,7 @@ from django.http import HttpRequest, HttpResponse
from zerver.decorator import webhook_view
from zerver.lib.actions import check_send_private_message
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.models import UserProfile, get_user
@ -35,7 +35,7 @@ def api_dialogflow_webhook(
body = f"{status} - {error_status}"
receiving_user = get_user(email, user_profile.realm)
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
check_send_private_message(user_profile, client, receiving_user, body)
return json_success()

View File

@ -5,7 +5,7 @@ from django.utils.translation import gettext as _
from zerver.decorator import webhook_view
from zerver.lib.actions import check_send_stream_message
from zerver.lib.exceptions import JsonableError
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.models import UserProfile
@ -35,7 +35,7 @@ def api_slack_webhook(
subject = _("Message from Slack")
content = ZULIP_MESSAGE_TEMPLATE.format(message_sender=user_name, text=text)
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
check_send_stream_message(user_profile, client, stream, subject, content)
return json_success()

View File

@ -10,7 +10,7 @@ from zerver.lib.actions import (
check_send_private_message,
send_rate_limited_pm_notification_to_bot_owner,
)
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.lib.send_email import FromAddress
from zerver.lib.webhooks.common import check_send_webhook_message
@ -137,7 +137,7 @@ def api_teamcity_webhook(
return json_success()
body = f"Your personal build for {body}"
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
check_send_private_message(user_profile, client, teamcity_user, body)

View File

@ -5,7 +5,7 @@ from django.http import HttpRequest, HttpResponse
from zerver.decorator import webhook_view
from zerver.lib.actions import check_send_private_message
from zerver.lib.request import REQ, get_request_notes, has_request_variables
from zerver.lib.request import REQ, RequestNotes, has_request_variables
from zerver.lib.response import json_success
from zerver.models import UserProfile, get_user
@ -22,7 +22,7 @@ def api_yo_app_webhook(
) -> HttpResponse:
body = f"Yo from {username}"
receiving_user = get_user(email, user_profile.realm)
client = get_request_notes(request).client
client = RequestNotes.get_notes(request).client
assert client is not None
check_send_private_message(user_profile, client, receiving_user, body)
return json_success()

View File

@ -8,7 +8,7 @@ from django.core.management.base import CommandParser
from django.http import HttpRequest, HttpResponse
from zerver.lib.management import ZulipBaseCommand
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.lib.test_helpers import HostRequestMock
from zerver.middleware import LogRequests
from zerver.models import UserMessage
@ -55,6 +55,6 @@ class Command(ZulipBaseCommand):
path="/",
)
mock_request.session = MockSession()
get_request_notes(mock_request).log_data = None
RequestNotes.get_notes(mock_request).log_data = None
profile_request(mock_request)

View File

@ -71,7 +71,7 @@ from zerver.lib.exceptions import JsonableError
from zerver.lib.mobile_auth_otp import is_valid_otp
from zerver.lib.rate_limiter import RateLimitedObject
from zerver.lib.redis_utils import get_dict_from_redis, get_redis_client, put_dict_in_redis
from zerver.lib.request import get_request_notes
from zerver.lib.request import RequestNotes
from zerver.lib.subdomains import get_subdomain
from zerver.lib.users import check_full_name, validate_user_custom_profile_field
from zerver.models import (
@ -251,7 +251,7 @@ def rate_limit_authentication_by_username(request: HttpRequest, username: str) -
def auth_rate_limiting_already_applied(request: HttpRequest) -> bool:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
return any(
isinstance(r.entity, RateLimitedAuthenticationByUsername)
@ -270,7 +270,7 @@ def rate_limit_auth(auth_func: AuthFuncT, *args: Any, **kwargs: Any) -> Optional
request = args[1]
username = kwargs["username"]
if get_request_notes(request).client is None or not client_is_exempt_from_rate_limiting(
if RequestNotes.get_notes(request).client is None or not client_is_exempt_from_rate_limiting(
request
):
# Django cycles through enabled authentication backends until one succeeds,

View File

@ -22,7 +22,7 @@ def add_context(event: "Event", hint: "Hint") -> Optional["Event"]:
return None
from django.conf import settings
from zerver.lib.request import get_current_request, get_request_notes
from zerver.lib.request import RequestNotes, get_current_request
from zerver.models import get_user_profile_by_id
with capture_internal_exceptions():
@ -47,7 +47,7 @@ def add_context(event: "Event", hint: "Hint") -> Optional["Event"]:
request = get_current_request()
if request:
request_notes = get_request_notes(request)
request_notes = RequestNotes.get_notes(request)
if request_notes.client is not None:
event["tags"]["client"] = request_notes.client.name
if request_notes.realm is not None: