1616
1717import logging
1818import re
19+ from typing import Pattern
1920
2021from six import string_types
2122
23+ from synapse .events import EventBase
2224from synapse .types import UserID
2325from synapse .util .caches import CACHE_SIZE_FACTOR , register_cache
2426from synapse .util .caches .lrucache import LruCache
@@ -56,18 +58,18 @@ def _test_ineq_condition(condition, number):
5658 rhs = m .group (2 )
5759 if not rhs .isdigit ():
5860 return False
59- rhs = int (rhs )
61+ rhs_int = int (rhs )
6062
6163 if ineq == "" or ineq == "==" :
62- return number == rhs
64+ return number == rhs_int
6365 elif ineq == "<" :
64- return number < rhs
66+ return number < rhs_int
6567 elif ineq == ">" :
66- return number > rhs
68+ return number > rhs_int
6769 elif ineq == ">=" :
68- return number >= rhs
70+ return number >= rhs_int
6971 elif ineq == "<=" :
70- return number <= rhs
72+ return number <= rhs_int
7173 else :
7274 return False
7375
@@ -83,7 +85,13 @@ def tweaks_for_actions(actions):
8385
8486
8587class PushRuleEvaluatorForEvent (object ):
86- def __init__ (self , event , room_member_count , sender_power_level , power_levels ):
88+ def __init__ (
89+ self ,
90+ event : EventBase ,
91+ room_member_count : int ,
92+ sender_power_level : int ,
93+ power_levels : dict ,
94+ ):
8795 self ._event = event
8896 self ._room_member_count = room_member_count
8997 self ._sender_power_level = sender_power_level
@@ -92,7 +100,7 @@ def __init__(self, event, room_member_count, sender_power_level, power_levels):
92100 # Maps strings of e.g. 'content.body' -> event["content"]["body"]
93101 self ._value_cache = _flatten_dict (event )
94102
95- def matches (self , condition , user_id , display_name ) :
103+ def matches (self , condition : dict , user_id : str , display_name : str ) -> bool :
96104 if condition ["kind" ] == "event_match" :
97105 return self ._event_match (condition , user_id )
98106 elif condition ["kind" ] == "contains_display_name" :
@@ -106,7 +114,7 @@ def matches(self, condition, user_id, display_name):
106114 else :
107115 return True
108116
109- def _event_match (self , condition , user_id ) :
117+ def _event_match (self , condition : dict , user_id : str ) -> bool :
110118 pattern = condition .get ("pattern" , None )
111119
112120 if not pattern :
@@ -134,59 +142,60 @@ def _event_match(self, condition, user_id):
134142
135143 return _glob_matches (pattern , haystack )
136144
137- def _contains_display_name (self , display_name ) :
145+ def _contains_display_name (self , display_name : str ) -> bool :
138146 if not display_name :
139147 return False
140148
141149 body = self ._event .content .get ("body" , None )
142150 if not body :
143151 return False
144152
145- return _glob_matches (display_name , body , word_boundary = True )
153+ # Similar to _glob_matches, but do not treat display_name as a glob.
154+ r = regex_cache .get ((display_name , False , True ), None )
155+ if not r :
156+ r = re .escape (display_name )
157+ r = _re_word_boundary (r )
158+ r = re .compile (r , flags = re .IGNORECASE )
159+ regex_cache [(display_name , False , True )] = r
160+
161+ return r .search (body )
146162
147- def _get_value (self , dotted_key ) :
163+ def _get_value (self , dotted_key : str ) -> str :
148164 return self ._value_cache .get (dotted_key , None )
149165
150166
151- # Caches (glob , word_boundary) -> regex for push. See _glob_matches
167+ # Caches (string, is_glob , word_boundary) -> regex for push. See _glob_matches
152168regex_cache = LruCache (50000 * CACHE_SIZE_FACTOR )
153169register_cache ("cache" , "regex_push_cache" , regex_cache )
154170
155171
156- def _glob_matches (glob , value , word_boundary = False ):
172+ def _glob_matches (glob : str , value : str , word_boundary : bool = False ) -> bool :
157173 """Tests if value matches glob.
158174
159175 Args:
160- glob (string)
161- value (string) : String to test against glob.
162- word_boundary (bool) : Whether to match against word boundaries or entire
176+ glob
177+ value: String to test against glob.
178+ word_boundary: Whether to match against word boundaries or entire
163179 string. Defaults to False.
164-
165- Returns:
166- bool
167180 """
168181
169182 try :
170- r = regex_cache .get ((glob , word_boundary ), None )
183+ r = regex_cache .get ((glob , True , word_boundary ), None )
171184 if not r :
172185 r = _glob_to_re (glob , word_boundary )
173- regex_cache [(glob , word_boundary )] = r
186+ regex_cache [(glob , True , word_boundary )] = r
174187 return r .search (value )
175188 except re .error :
176189 logger .warning ("Failed to parse glob to regex: %r" , glob )
177190 return False
178191
179192
180- def _glob_to_re (glob , word_boundary ) :
193+ def _glob_to_re (glob : str , word_boundary : bool ) -> Pattern :
181194 """Generates regex for a given glob.
182195
183196 Args:
184- glob (string)
185- word_boundary (bool): Whether to match against word boundaries or entire
186- string. Defaults to False.
187-
188- Returns:
189- regex object
197+ glob
198+ word_boundary: Whether to match against word boundaries or entire string.
190199 """
191200 if IS_GLOB .search (glob ):
192201 r = re .escape (glob )
@@ -219,7 +228,7 @@ def _glob_to_re(glob, word_boundary):
219228 return re .compile (r , flags = re .IGNORECASE )
220229
221230
222- def _re_word_boundary (r ) :
231+ def _re_word_boundary (r : str ) -> str :
223232 """
224233 Adds word boundary characters to the start and end of an
225234 expression to require that the match occur as a whole word,
0 commit comments