From 68fe912c6301648ec321188c3ee3cb4ef7e8ec98 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Bodas Date: Tue, 30 Mar 2021 15:45:39 +0530 Subject: [PATCH] refactor: Rename most of "filter" to "linkifier". After this only the database table, events, and API endpoints remain. --- zerver/lib/actions.py | 14 +- zerver/lib/events.py | 4 +- zerver/lib/markdown/__init__.py | 121 +++++++++--------- zerver/management/commands/edit_linkifiers.py | 10 +- zerver/models.py | 48 +++---- zerver/openapi/curl_param_value_generators.py | 4 +- zerver/tests/test_events.py | 10 +- zerver/tests/test_markdown.py | 40 +++--- zerver/tests/test_realm_linkifiers.py | 14 +- zerver/views/realm_linkifiers.py | 22 ++-- zproject/urls.py | 6 +- 11 files changed, 144 insertions(+), 149 deletions(-) diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 1a728d948f..5525b49c30 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -232,8 +232,8 @@ from zerver.models import ( get_user_by_id_in_realm_including_cross_realm, get_user_profile_by_id, is_cross_realm_bot_email, + linkifiers_for_realm, query_for_ids, - realm_filters_for_realm, validate_attachment_request, ) from zerver.tornado.django_api import send_event @@ -6492,8 +6492,8 @@ def do_mark_hotspot_as_read(user: UserProfile, hotspot: str) -> None: send_event(user.realm, event, [user.id]) -def notify_realm_filters(realm: Realm) -> None: - realm_filters = realm_filters_for_realm(realm.id) +def notify_linkifiers(realm: Realm) -> None: + realm_filters = linkifiers_for_realm(realm.id) event = dict(type="realm_filters", realm_filters=realm_filters) send_event(realm, event, active_user_ids(realm.id)) @@ -6502,25 +6502,25 @@ def notify_realm_filters(realm: Realm) -> None: # RegExp syntax. In addition to JS-compatible syntax, the following features are available: # * Named groups will be converted to numbered groups automatically # * Inline-regex flags will be stripped, and where possible translated to RegExp-wide flags -def do_add_realm_filter(realm: Realm, pattern: str, url_format_string: str) -> int: +def do_add_linkifier(realm: Realm, pattern: str, url_format_string: str) -> int: pattern = pattern.strip() url_format_string = url_format_string.strip() linkifier = RealmFilter(realm=realm, pattern=pattern, url_format_string=url_format_string) linkifier.full_clean() linkifier.save() - notify_realm_filters(realm) + notify_linkifiers(realm) return linkifier.id -def do_remove_realm_filter( +def do_remove_linkifier( realm: Realm, pattern: Optional[str] = None, id: Optional[int] = None ) -> None: if pattern is not None: RealmFilter.objects.get(realm=realm, pattern=pattern).delete() else: RealmFilter.objects.get(realm=realm, pk=id).delete() - notify_realm_filters(realm) + notify_linkifiers(realm) def get_emails_from_user_ids(user_ids: Sequence[int]) -> Dict[int, str]: diff --git a/zerver/lib/events.py b/zerver/lib/events.py index 83f6dfd647..141199f942 100644 --- a/zerver/lib/events.py +++ b/zerver/lib/events.py @@ -58,7 +58,7 @@ from zerver.models import ( custom_profile_fields_for_realm, get_default_stream_groups, get_realm_domains, - realm_filters_for_realm, + linkifiers_for_realm, ) from zerver.tornado.django_api import get_user_events, request_event_queue from zproject.backends import email_auth_enabled, password_auth_enabled @@ -252,7 +252,7 @@ def fetch_initial_state_data( state["realm_emoji"] = realm.get_emoji() if want("realm_filters"): - state["realm_filters"] = realm_filters_for_realm(realm.id) + state["realm_filters"] = linkifiers_for_realm(realm.id) if want("realm_user_groups"): state["realm_user_groups"] = user_groups_in_realm_serialized(realm) diff --git a/zerver/lib/markdown/__init__.py b/zerver/lib/markdown/__init__.py index 4624b0bb3e..e4b81475af 100644 --- a/zerver/lib/markdown/__init__.py +++ b/zerver/lib/markdown/__init__.py @@ -72,9 +72,9 @@ from zerver.models import ( UserGroup, UserGroupMembership, UserProfile, - all_realm_filters, + all_linkifiers_for_installation, get_active_streams, - realm_filters_for_realm, + linkifiers_for_realm, ) ReturnT = TypeVar("ReturnT") @@ -1780,7 +1780,7 @@ class MarkdownListPreprocessor(markdown.preprocessors.Preprocessor): OUTER_CAPTURE_GROUP = "linkifier_actual_match" -def prepare_realm_pattern(source: str) -> str: +def prepare_linkifier_pattern(source: str) -> str: """Augment a linkifier so it only matches after start-of-string, whitespace, or opening delimiters, won't match if there are word characters directly after, and saves what was matched as @@ -1790,8 +1790,8 @@ def prepare_realm_pattern(source: str) -> str: # Given a regular expression pattern, linkifies groups that match it # using the provided format string to construct the URL. -class RealmFilterPattern(markdown.inlinepatterns.Pattern): - """ Applied a given realm filter to the input """ +class LinkifierPattern(markdown.inlinepatterns.Pattern): + """ Applied a given linkifier to the input """ def __init__( self, @@ -1799,7 +1799,7 @@ class RealmFilterPattern(markdown.inlinepatterns.Pattern): format_string: str, markdown_instance: Optional[markdown.Markdown] = None, ) -> None: - self.pattern = prepare_realm_pattern(source_pattern) + self.pattern = prepare_linkifier_pattern(source_pattern) self.format_string = format_string markdown.inlinepatterns.Pattern.__init__(self, self.pattern, markdown_instance) @@ -2088,8 +2088,8 @@ def get_sub_registry(r: markdown.util.Registry, keys: List[str]) -> markdown.uti return new_r -# These are used as keys ("realm_filters_keys") to md_engines and the respective -# realm filter caches +# These are used as keys ("linkifiers_keys") to md_engines and the respective +# linkifier caches DEFAULT_MARKDOWN_KEY = -1 ZEPHYR_MIRROR_MARKDOWN_KEY = -2 @@ -2103,12 +2103,12 @@ class Markdown(markdown.Markdown): def __init__( self, - realm_filters: List[Tuple[str, str, int]], - realm_filters_key: int, + linkifiers: List[Tuple[str, str, int]], + linkifiers_key: int, email_gateway: bool, ) -> None: - self.realm_filters = realm_filters - self.realm_filters_key = realm_filters_key + self.linkifiers = linkifiers + self.linkifiers_key = linkifiers_key self.email_gateway = email_gateway super().__init__( @@ -2231,8 +2231,8 @@ class Markdown(markdown.Markdown): ) reg.register(LinkInlineProcessor(markdown.inlinepatterns.LINK_RE, self), "link", 60) reg.register(AutoLink(get_web_link_regex(), self), "autolink", 55) - # Reserve priority 45-54 for realm filters - reg = self.register_realm_filters(reg) + # Reserve priority 45-54 for linkifiers + reg = self.register_linkifiers(reg) reg.register(markdown.inlinepatterns.HtmlInlineProcessor(ENTITY_RE, self), "entity", 40) reg.register( markdown.inlinepatterns.SimpleTagPattern(r"(\*\*)([^\n]+?)\2", "strong"), "strong", 35 @@ -2248,12 +2248,12 @@ class Markdown(markdown.Markdown): reg.register(UnicodeEmoji(unicode_emoji_regex), "unicodeemoji", 0) return reg - def register_realm_filters( - self, inlinePatterns: markdown.util.Registry - ) -> markdown.util.Registry: - for (pattern, format_string, id) in self.realm_filters: + def register_linkifiers(self, inlinePatterns: markdown.util.Registry) -> markdown.util.Registry: + for (pattern, format_string, id) in self.linkifiers: inlinePatterns.register( - RealmFilterPattern(pattern, format_string, self), f"realm_filters/{pattern}", 45 + LinkifierPattern(pattern, format_string, self), + f"linkifiers/{pattern}", + 45, ) return inlinePatterns @@ -2281,7 +2281,7 @@ class Markdown(markdown.Markdown): return postprocessors def handle_zephyr_mirror(self) -> None: - if self.realm_filters_key == ZEPHYR_MIRROR_MARKDOWN_KEY: + if self.linkifiers_key == ZEPHYR_MIRROR_MARKDOWN_KEY: # Disable almost all inline patterns for zephyr mirror # users' traffic that is mirrored. Note that # inline_interesting_links is a treeprocessor and thus is @@ -2302,18 +2302,18 @@ class Markdown(markdown.Markdown): md_engines: Dict[Tuple[int, bool], Markdown] = {} -realm_filter_data: Dict[int, List[Tuple[str, str, int]]] = {} +linkifier_data: Dict[int, List[Tuple[str, str, int]]] = {} -def make_md_engine(realm_filters_key: int, email_gateway: bool) -> None: - md_engine_key = (realm_filters_key, email_gateway) +def make_md_engine(linkifiers_key: int, email_gateway: bool) -> None: + md_engine_key = (linkifiers_key, email_gateway) if md_engine_key in md_engines: del md_engines[md_engine_key] - realm_filters = realm_filter_data[realm_filters_key] + linkifiers = linkifier_data[linkifiers_key] md_engines[md_engine_key] = Markdown( - realm_filters=realm_filters, - realm_filters_key=realm_filters_key, + linkifiers=linkifiers, + linkifiers_key=linkifiers_key, email_gateway=email_gateway, ) @@ -2326,18 +2326,18 @@ basic_link_splitter = re.compile(r"[ !;\?\),\'\"]") # function on the URLs; they are expected to be HTML-escaped when # rendered by clients (just as links rendered into message bodies # are validated and escaped inside `url_to_a`). -def topic_links(realm_filters_key: int, topic_name: str) -> List[Dict[str, str]]: +def topic_links(linkifiers_key: int, topic_name: str) -> List[Dict[str, str]]: matches: List[Dict[str, Union[str, int]]] = [] - realm_filters = realm_filters_for_realm(realm_filters_key) + linkifiers = linkifiers_for_realm(linkifiers_key) - for realm_filter in realm_filters: - raw_pattern = realm_filter[0] - url_format_string = realm_filter[1] - pattern = prepare_realm_pattern(raw_pattern) + for linkifier in linkifiers: + raw_pattern = linkifier[0] + url_format_string = linkifier[1] + pattern = prepare_linkifier_pattern(raw_pattern) for m in re.finditer(pattern, topic_name): match_details = m.groupdict() match_text = match_details["linkifier_actual_match"] - # We format the realm_filter's url string using the matched text. + # We format the linkifier's url string using the matched text. # Also, we include the matched text in the response, so that our clients # don't have to implement any logic of their own to get back the text. matches += [ @@ -2371,35 +2371,32 @@ def topic_links(realm_filters_key: int, topic_name: str) -> List[Dict[str, str]] return [{k: str(v) for k, v in match.items() if k != "index"} for match in matches] -def maybe_update_markdown_engines(realm_filters_key: Optional[int], email_gateway: bool) -> None: - # If realm_filters_key is None, load all filters - global realm_filter_data - if realm_filters_key is None: - all_filters = all_realm_filters() - all_filters[DEFAULT_MARKDOWN_KEY] = [] - for realm_filters_key, filters in all_filters.items(): - realm_filter_data[realm_filters_key] = filters - make_md_engine(realm_filters_key, email_gateway) - # Hack to ensure that realm_filters_key is right for mirrored Zephyrs - realm_filter_data[ZEPHYR_MIRROR_MARKDOWN_KEY] = [] +def maybe_update_markdown_engines(linkifiers_key: Optional[int], email_gateway: bool) -> None: + # If linkifiers_key is None, load all linkifiers + global linkifier_data + if linkifiers_key is None: + all_linkifiers = all_linkifiers_for_installation() + all_linkifiers[DEFAULT_MARKDOWN_KEY] = [] + for linkifiers_key, linkifiers in all_linkifiers.items(): + linkifier_data[linkifiers_key] = linkifiers + make_md_engine(linkifiers_key, email_gateway) + # Hack to ensure that linkifiers_key is right for mirrored Zephyrs + linkifier_data[ZEPHYR_MIRROR_MARKDOWN_KEY] = [] make_md_engine(ZEPHYR_MIRROR_MARKDOWN_KEY, False) else: - realm_filters = realm_filters_for_realm(realm_filters_key) - if ( - realm_filters_key not in realm_filter_data - or realm_filter_data[realm_filters_key] != realm_filters - ): - # Realm filters data has changed, update `realm_filter_data` and any - # of the existing Markdown engines using this set of realm filters. - realm_filter_data[realm_filters_key] = realm_filters + linkifiers = linkifiers_for_realm(linkifiers_key) + if linkifiers_key not in linkifier_data or linkifier_data[linkifiers_key] != linkifiers: + # Linkifier data has changed, update `linkifier_data` and any + # of the existing Markdown engines using this set of linkifiers. + linkifier_data[linkifiers_key] = linkifiers for email_gateway_flag in [True, False]: - if (realm_filters_key, email_gateway_flag) in md_engines: + if (linkifiers_key, email_gateway_flag) in md_engines: # Update only existing engines(if any), don't create new one. - make_md_engine(realm_filters_key, email_gateway_flag) + make_md_engine(linkifiers_key, email_gateway_flag) - if (realm_filters_key, email_gateway) not in md_engines: + if (linkifiers_key, email_gateway) not in md_engines: # Markdown engine corresponding to this key doesn't exists so create one. - make_md_engine(realm_filters_key, email_gateway) + make_md_engine(linkifiers_key, email_gateway) # We want to log Markdown parser failures, but shouldn't log the actual input @@ -2561,9 +2558,9 @@ def do_convert( if message_realm is None: message_realm = message.get_realm() if message_realm is None: - realm_filters_key = DEFAULT_MARKDOWN_KEY + linkifiers_key = DEFAULT_MARKDOWN_KEY else: - realm_filters_key = message_realm.id + linkifiers_key = message_realm.id if message and hasattr(message, "id") and message.id: logging_message_id = "id# " + str(message.id) @@ -2575,16 +2572,16 @@ def do_convert( if message.sending_client.name == "zephyr_mirror": # Use slightly customized Markdown processor for content # delivered via zephyr_mirror - realm_filters_key = ZEPHYR_MIRROR_MARKDOWN_KEY + linkifiers_key = ZEPHYR_MIRROR_MARKDOWN_KEY - maybe_update_markdown_engines(realm_filters_key, email_gateway) - md_engine_key = (realm_filters_key, email_gateway) + maybe_update_markdown_engines(linkifiers_key, email_gateway) + md_engine_key = (linkifiers_key, email_gateway) if md_engine_key in md_engines: _md_engine = md_engines[md_engine_key] else: if DEFAULT_MARKDOWN_KEY not in md_engines: - maybe_update_markdown_engines(realm_filters_key=None, email_gateway=False) + maybe_update_markdown_engines(linkifiers_key=None, email_gateway=False) _md_engine = md_engines[(DEFAULT_MARKDOWN_KEY, email_gateway)] # Reset the parser; otherwise it will get slower over time. diff --git a/zerver/management/commands/edit_linkifiers.py b/zerver/management/commands/edit_linkifiers.py index 7a83d57808..30f821da78 100644 --- a/zerver/management/commands/edit_linkifiers.py +++ b/zerver/management/commands/edit_linkifiers.py @@ -2,9 +2,9 @@ import sys from argparse import ArgumentParser from typing import Any -from zerver.lib.actions import do_add_realm_filter, do_remove_realm_filter +from zerver.lib.actions import do_add_linkifier, do_remove_linkifier from zerver.lib.management import CommandError, ZulipBaseCommand -from zerver.models import all_realm_filters +from zerver.models import all_linkifiers_for_installation class Command(ZulipBaseCommand): @@ -41,7 +41,7 @@ Example: ./manage.py realm_filters --realm=zulip --op=show realm = self.get_realm(options) assert realm is not None # Should be ensured by parser if options["op"] == "show": - print(f"{realm.string_id}: {all_realm_filters().get(realm.id, [])}") + print(f"{realm.string_id}: {all_linkifiers_for_installation().get(realm.id, [])}") sys.exit(0) pattern = options["pattern"] @@ -54,10 +54,10 @@ Example: ./manage.py realm_filters --realm=zulip --op=show if not url_format_string: self.print_help("./manage.py", "realm_filters") raise CommandError - do_add_realm_filter(realm, pattern, url_format_string) + do_add_linkifier(realm, pattern, url_format_string) sys.exit(0) elif options["op"] == "remove": - do_remove_realm_filter(realm, pattern=pattern) + do_remove_linkifier(realm, pattern=pattern) sys.exit(0) else: self.print_help("./manage.py", "realm_filters") diff --git a/zerver/models.py b/zerver/models.py index b355cdc5a8..f4498106a6 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -887,61 +887,61 @@ class RealmFilter(models.Model): return f"" -def get_realm_filters_cache_key(realm_id: int) -> str: - return f"{cache.KEY_PREFIX}:all_realm_filters:{realm_id}" +def get_linkifiers_cache_key(realm_id: int) -> str: + return f"{cache.KEY_PREFIX}:all_linkifiers_for_realm:{realm_id}" # We have a per-process cache to avoid doing 1000 remote cache queries during page load -per_request_realm_filters_cache: Dict[int, List[Tuple[str, str, int]]] = {} +per_request_linkifiers_cache: Dict[int, List[Tuple[str, str, int]]] = {} -def realm_in_local_realm_filters_cache(realm_id: int) -> bool: - return realm_id in per_request_realm_filters_cache +def realm_in_local_linkifiers_cache(realm_id: int) -> bool: + return realm_id in per_request_linkifiers_cache -def realm_filters_for_realm(realm_id: int) -> List[Tuple[str, str, int]]: - if not realm_in_local_realm_filters_cache(realm_id): - per_request_realm_filters_cache[realm_id] = realm_filters_for_realm_remote_cache(realm_id) - return per_request_realm_filters_cache[realm_id] +def linkifiers_for_realm(realm_id: int) -> List[Tuple[str, str, int]]: + if not realm_in_local_linkifiers_cache(realm_id): + per_request_linkifiers_cache[realm_id] = linkifiers_for_realm_remote_cache(realm_id) + return per_request_linkifiers_cache[realm_id] -@cache_with_key(get_realm_filters_cache_key, timeout=3600 * 24 * 7) -def realm_filters_for_realm_remote_cache(realm_id: int) -> List[Tuple[str, str, int]]: +@cache_with_key(get_linkifiers_cache_key, timeout=3600 * 24 * 7) +def linkifiers_for_realm_remote_cache(realm_id: int) -> List[Tuple[str, str, int]]: filters = [] - for realm_filter in RealmFilter.objects.filter(realm_id=realm_id): - filters.append((realm_filter.pattern, realm_filter.url_format_string, realm_filter.id)) + for linkifier in RealmFilter.objects.filter(realm_id=realm_id): + filters.append((linkifier.pattern, linkifier.url_format_string, linkifier.id)) return filters -def all_realm_filters() -> Dict[int, List[Tuple[str, str, int]]]: +def all_linkifiers_for_installation() -> Dict[int, List[Tuple[str, str, int]]]: filters: DefaultDict[int, List[Tuple[str, str, int]]] = defaultdict(list) - for realm_filter in RealmFilter.objects.all(): - filters[realm_filter.realm_id].append( - (realm_filter.pattern, realm_filter.url_format_string, realm_filter.id) + for linkifier in RealmFilter.objects.all(): + filters[linkifier.realm_id].append( + (linkifier.pattern, linkifier.url_format_string, linkifier.id) ) return filters -def flush_realm_filter(sender: Any, **kwargs: Any) -> None: +def flush_linkifiers(sender: Any, **kwargs: Any) -> None: realm_id = kwargs["instance"].realm_id - cache_delete(get_realm_filters_cache_key(realm_id)) + cache_delete(get_linkifiers_cache_key(realm_id)) try: - per_request_realm_filters_cache.pop(realm_id) + per_request_linkifiers_cache.pop(realm_id) except KeyError: pass -post_save.connect(flush_realm_filter, sender=RealmFilter) -post_delete.connect(flush_realm_filter, sender=RealmFilter) +post_save.connect(flush_linkifiers, sender=RealmFilter) +post_delete.connect(flush_linkifiers, sender=RealmFilter) def flush_per_request_caches() -> None: global per_request_display_recipient_cache per_request_display_recipient_cache = {} - global per_request_realm_filters_cache - per_request_realm_filters_cache = {} + global per_request_linkifiers_cache + per_request_linkifiers_cache = {} # The Recipient table is used to map Messages to the set of users who diff --git a/zerver/openapi/curl_param_value_generators.py b/zerver/openapi/curl_param_value_generators.py index 27d449377d..1be861e71d 100644 --- a/zerver/openapi/curl_param_value_generators.py +++ b/zerver/openapi/curl_param_value_generators.py @@ -12,8 +12,8 @@ from typing import Any, Callable, Dict, List, Optional, Set, Tuple from django.utils.timezone import now as timezone_now from zerver.lib.actions import ( + do_add_linkifier, do_add_reaction, - do_add_realm_filter, do_create_user, update_user_presence, ) @@ -253,7 +253,7 @@ def get_temp_user_group_id() -> Dict[str, object]: @openapi_param_value_generator(["/realm/filters/{filter_id}:delete"]) def remove_realm_filters() -> Dict[str, object]: - filter_id = do_add_realm_filter( + filter_id = do_add_linkifier( get_realm("zulip"), "#(?P[0-9]{2,8})", "https://github.com/zulip/zulip/pull/%(id)s" ) return { diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index cfa751b6e5..a67ba4bbe2 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -24,9 +24,9 @@ from zerver.lib.actions import ( check_send_typing_notification, do_add_alert_words, do_add_default_stream, + do_add_linkifier, do_add_reaction, do_add_realm_domain, - do_add_realm_filter, do_add_streams_to_default_stream_group, do_add_submessage, do_change_avatar_fields, @@ -64,11 +64,11 @@ from zerver.lib.actions import ( do_remove_alert_words, do_remove_default_stream, do_remove_default_stream_group, + do_remove_linkifier, do_remove_reaction, do_remove_realm_custom_profile_field, do_remove_realm_domain, do_remove_realm_emoji, - do_remove_realm_filter, do_remove_streams_from_default_stream_group, do_rename_stream, do_revoke_multi_use_invite, @@ -1318,13 +1318,11 @@ class NormalActionsTest(BaseAction): regex = "#(?P[123])" url = "https://realm.com/my_realm_filter/%(id)s" - events = self.verify_action( - lambda: do_add_realm_filter(self.user_profile.realm, regex, url) - ) + events = self.verify_action(lambda: do_add_linkifier(self.user_profile.realm, regex, url)) check_realm_filters("events[0]", events[0]) events = self.verify_action( - lambda: do_remove_realm_filter(self.user_profile.realm, "#(?P[123])") + lambda: do_remove_linkifier(self.user_profile.realm, "#(?P[123])") ) check_realm_filters("events[0]", events[0]) diff --git a/zerver/tests/test_markdown.py b/zerver/tests/test_markdown.py index a4039ad6c5..b1815dd6ad 100644 --- a/zerver/tests/test_markdown.py +++ b/zerver/tests/test_markdown.py @@ -55,13 +55,13 @@ from zerver.models import ( UserGroup, UserMessage, UserProfile, + flush_linkifiers, flush_per_request_caches, - flush_realm_filter, get_client, get_realm, get_stream, - realm_filters_for_realm, - realm_in_local_realm_filters_cache, + linkifiers_for_realm, + realm_in_local_linkifiers_cache, ) @@ -1429,13 +1429,13 @@ class MarkdownTest(ZulipTestCase): import zerver.lib.markdown - zerver.lib.markdown.realm_filter_data = {} + zerver.lib.markdown.linkifier_data = {} maybe_update_markdown_engines(None, False) - all_filters = zerver.lib.markdown.realm_filter_data - zulip_filters = all_filters[realm.id] - self.assertEqual(len(zulip_filters), 1) + all_linkifiers = zerver.lib.markdown.linkifier_data + zulip_linkifiers = all_linkifiers[realm.id] + self.assertEqual(len(zulip_linkifiers), 1) self.assertEqual( - zulip_filters[0], + zulip_linkifiers[0], ("#(?P[0-9]{2,8})", "https://trac.example.com/ticket/%(id)s", linkifier.id), ) @@ -1444,7 +1444,7 @@ class MarkdownTest(ZulipTestCase): def flush() -> None: """ - flush_realm_filter is a post-save hook, so calling it + flush_linkifiers is a post-save hook, so calling it directly for testing is kind of awkward """ @@ -1453,30 +1453,28 @@ class MarkdownTest(ZulipTestCase): instance = Instance() instance.realm_id = realm.id - flush_realm_filter(sender=None, instance=instance) + flush_linkifiers(sender=None, instance=instance) - def save_new_realm_filter() -> None: - realm_filter = RealmFilter( - realm=realm, pattern=r"whatever", url_format_string="whatever" - ) - realm_filter.save() + def save_new_linkifier() -> None: + linkifier = RealmFilter(realm=realm, pattern=r"whatever", url_format_string="whatever") + linkifier.save() # start fresh for our realm flush() - self.assertFalse(realm_in_local_realm_filters_cache(realm.id)) + self.assertFalse(realm_in_local_linkifiers_cache(realm.id)) # call this just for side effects of populating the cache - realm_filters_for_realm(realm.id) - self.assertTrue(realm_in_local_realm_filters_cache(realm.id)) + linkifiers_for_realm(realm.id) + self.assertTrue(realm_in_local_linkifiers_cache(realm.id)) # Saving a new RealmFilter should have the side effect of # flushing the cache. - save_new_realm_filter() - self.assertFalse(realm_in_local_realm_filters_cache(realm.id)) + save_new_linkifier() + self.assertFalse(realm_in_local_linkifiers_cache(realm.id)) # and flush it one more time, to make sure we don't get a KeyError flush() - self.assertFalse(realm_in_local_realm_filters_cache(realm.id)) + self.assertFalse(realm_in_local_linkifiers_cache(realm.id)) def test_realm_patterns_negative(self) -> None: realm = get_realm("zulip") diff --git a/zerver/tests/test_realm_linkifiers.py b/zerver/tests/test_realm_linkifiers.py index 8777e2d8c1..630e0fc26f 100644 --- a/zerver/tests/test_realm_linkifiers.py +++ b/zerver/tests/test_realm_linkifiers.py @@ -1,6 +1,6 @@ import re -from zerver.lib.actions import do_add_realm_filter +from zerver.lib.actions import do_add_linkifier from zerver.lib.test_classes import ZulipTestCase from zerver.models import RealmFilter, get_realm @@ -9,7 +9,7 @@ class RealmFilterTest(ZulipTestCase): def test_list(self) -> None: self.login("iago") realm = get_realm("zulip") - do_add_realm_filter(realm, "#(?P[123])", "https://realm.com/my_realm_filter/%(id)s") + do_add_linkifier(realm, "#(?P[123])", "https://realm.com/my_realm_filter/%(id)s") result = self.client_get("/json/realm/filters") self.assert_json_success(result) self.assertEqual(200, result.status_code) @@ -104,13 +104,13 @@ class RealmFilterTest(ZulipTestCase): def test_delete(self) -> None: self.login("iago") realm = get_realm("zulip") - filter_id = do_add_realm_filter( + linkifier_id = do_add_linkifier( realm, "#(?P[123])", "https://realm.com/my_realm_filter/%(id)s" ) - filters_count = RealmFilter.objects.count() - result = self.client_delete(f"/json/realm/filters/{filter_id + 1}") + linkifiers_count = RealmFilter.objects.count() + result = self.client_delete(f"/json/realm/filters/{linkifier_id + 1}") self.assert_json_error(result, "Filter not found") - result = self.client_delete(f"/json/realm/filters/{filter_id}") + result = self.client_delete(f"/json/realm/filters/{linkifier_id}") self.assert_json_success(result) - self.assertEqual(RealmFilter.objects.count(), filters_count - 1) + self.assertEqual(RealmFilter.objects.count(), linkifiers_count - 1) diff --git a/zerver/views/realm_linkifiers.py b/zerver/views/realm_linkifiers.py index 0fc8eb527d..e7c522a7b2 100644 --- a/zerver/views/realm_linkifiers.py +++ b/zerver/views/realm_linkifiers.py @@ -3,41 +3,43 @@ from django.http import HttpRequest, HttpResponse from django.utils.translation import ugettext as _ from zerver.decorator import require_realm_admin -from zerver.lib.actions import do_add_realm_filter, do_remove_realm_filter +from zerver.lib.actions import do_add_linkifier, do_remove_linkifier from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_error, json_success -from zerver.models import RealmFilter, UserProfile, realm_filters_for_realm +from zerver.models import RealmFilter, UserProfile, linkifiers_for_realm -# Custom realm filters -def list_filters(request: HttpRequest, user_profile: UserProfile) -> HttpResponse: - filters = realm_filters_for_realm(user_profile.realm_id) +# Custom realm linkifiers +def list_linkifiers(request: HttpRequest, user_profile: UserProfile) -> HttpResponse: + filters = linkifiers_for_realm(user_profile.realm_id) return json_success({"filters": filters}) @require_realm_admin @has_request_variables -def create_filter( +def create_linkifier( request: HttpRequest, user_profile: UserProfile, pattern: str = REQ(), url_format_string: str = REQ(), ) -> HttpResponse: try: - filter_id = do_add_realm_filter( + linkifier_id = do_add_linkifier( realm=user_profile.realm, pattern=pattern, url_format_string=url_format_string, ) - return json_success({"id": filter_id}) + return json_success({"id": linkifier_id}) except ValidationError as e: return json_error(e.messages[0], data={"errors": dict(e)}) @require_realm_admin -def delete_filter(request: HttpRequest, user_profile: UserProfile, filter_id: int) -> HttpResponse: +def delete_linkifier( + request: HttpRequest, user_profile: UserProfile, filter_id: int +) -> HttpResponse: try: - do_remove_realm_filter(realm=user_profile.realm, id=filter_id) + do_remove_linkifier(realm=user_profile.realm, id=filter_id) except RealmFilter.DoesNotExist: return json_error(_("Filter not found")) return json_success() diff --git a/zproject/urls.py b/zproject/urls.py index 55923d1415..3bdeebe7c0 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -119,7 +119,7 @@ from zerver.views.realm_domains import ( from zerver.views.realm_emoji import delete_emoji, list_emoji, upload_emoji from zerver.views.realm_export import delete_realm_export, export_realm, get_realm_exports from zerver.views.realm_icon import delete_icon_backend, get_icon_backend, upload_icon -from zerver.views.realm_linkifiers import create_filter, delete_filter, list_filters +from zerver.views.realm_linkifiers import create_linkifier, delete_linkifier, list_linkifiers from zerver.views.realm_logo import delete_logo_backend, get_logo_backend, upload_logo from zerver.views.registration import ( accounts_home, @@ -266,8 +266,8 @@ v1_api_and_json_patterns = [ # realm/logo -> zerver.views.realm_logo rest_path("realm/logo", POST=upload_logo, DELETE=delete_logo_backend, GET=get_logo_backend), # realm/filters -> zerver.views.realm_linkifiers - rest_path("realm/filters", GET=list_filters, POST=create_filter), - rest_path("realm/filters/", DELETE=delete_filter), + rest_path("realm/filters", GET=list_linkifiers, POST=create_linkifier), + rest_path("realm/filters/", DELETE=delete_linkifier), # realm/profile_fields -> zerver.views.custom_profile_fields rest_path( "realm/profile_fields",