77from itertools import chain
88
99
10- current_word_re = re .compile (r'[\w_][\w0-9._]*[(]?' )
10+ class LazyReCompile (object ):
11+
12+ def __init__ (self , regex ):
13+ self .regex = regex
14+ self .compiled = None
15+
16+ def compile_regex (method ):
17+ def _impl (self , * args , ** kwargs ):
18+ if self .compiled is None :
19+ self .compiled = re .compile (self .regex )
20+ return method (self , * args , ** kwargs )
21+ return _impl
22+
23+ @compile_regex
24+ def finditer (self , * args , ** kwargs ):
25+ return self .compiled .finditer (* args , ** kwargs )
26+
27+ @compile_regex
28+ def search (self , * args , ** kwargs ):
29+ return self .compiled .search (* args , ** kwargs )
30+
31+ @compile_regex
32+ def match (self , * args , ** kwargs ):
33+ return self .compiled .match (* args , ** kwargs )
34+
35+
36+ current_word_re = LazyReCompile (r'[\w_][\w0-9._]*[(]?' )
37+
1138
1239def current_word (cursor_offset , line ):
1340 """the object.attribute.attribute just before or under the cursor"""
@@ -26,7 +53,7 @@ def current_word(cursor_offset, line):
2653 return (start , end , word )
2754
2855
29- current_dict_key_re = re . compile (r'''[\w_][\w0-9._]*\[([\w0-9._(), '"]*)''' )
56+ current_dict_key_re = LazyReCompile (r'''[\w_][\w0-9._]*\[([\w0-9._(), '"]*)''' )
3057
3158def current_dict_key (cursor_offset , line ):
3259 """If in dictionary completion, return the current key"""
@@ -37,7 +64,8 @@ def current_dict_key(cursor_offset, line):
3764 return None
3865
3966
40- current_dict_re = re .compile (r'''([\w_][\w0-9._]*)\[([\w0-9._(), '"]*)''' )
67+ current_dict_re = LazyReCompile (r'''([\w_][\w0-9._]*)\[([\w0-9._(), '"]*)''' )
68+
4169
4270def current_dict (cursor_offset , line ):
4371 """If in dictionary completion, return the dict that should be used"""
@@ -48,9 +76,10 @@ def current_dict(cursor_offset, line):
4876 return None
4977
5078
51- current_string_re = re . compile (
79+ current_string_re = LazyReCompile (
5280 '''(?P<open>(?:""")|"|(?:''\' )|')(?:((?P<closed>.+?)(?P=open))|(?P<unclosed>.+))''' )
5381
82+
5483def current_string (cursor_offset , line ):
5584 """If inside a string of nonzero length, return the string (excluding quotes)
5685
@@ -63,7 +92,7 @@ def current_string(cursor_offset, line):
6392 return None
6493
6594
66- current_object_re = re . compile (r'([\w_][\w0-9_]*)[.]' )
95+ current_object_re = LazyReCompile (r'([\w_][\w0-9_]*)[.]' )
6796
6897def current_object (cursor_offset , line ):
6998 """If in attribute completion, the object on which attribute should be looked up"""
@@ -82,7 +111,7 @@ def current_object(cursor_offset, line):
82111 return start , start + len (s ), s
83112
84113
85- current_object_attribute_re = re . compile (r'([\w_][\w0-9_]*)[.]?' )
114+ current_object_attribute_re = LazyReCompile (r'([\w_][\w0-9_]*)[.]?' )
86115
87116def current_object_attribute (cursor_offset , line ):
88117 """If in attribute completion, the attribute being completed"""
@@ -97,7 +126,7 @@ def current_object_attribute(cursor_offset, line):
97126 return None
98127
99128
100- current_from_import_from_re = re . compile (r'from ([\w0-9_.]*)(?:\s+import\s+([\w0-9_]+[,]?\s*)+)*' )
129+ current_from_import_from_re = LazyReCompile (r'from ([\w0-9_.]*)(?:\s+import\s+([\w0-9_]+[,]?\s*)+)*' )
101130
102131def current_from_import_from (cursor_offset , line ):
103132 """If in from import completion, the word after from
@@ -117,9 +146,9 @@ def current_from_import_from(cursor_offset, line):
117146 return None
118147
119148
120- current_from_import_import_re_1 = re . compile (r'from\s([\w0-9_.]*)\s+import' )
121- current_from_import_import_re_2 = re . compile (r'([\w0-9_]+)' )
122- current_from_import_import_re_3 = re . compile (r'[,][ ]([\w0-9_]*)' )
149+ current_from_import_import_re_1 = LazyReCompile (r'from\s([\w0-9_.]*)\s+import' )
150+ current_from_import_import_re_2 = LazyReCompile (r'([\w0-9_]+)' )
151+ current_from_import_import_re_3 = LazyReCompile (r'[,][ ]([\w0-9_]*)' )
123152
124153def current_from_import_import (cursor_offset , line ):
125154 """If in from import completion, the word after import being completed
@@ -141,9 +170,9 @@ def current_from_import_import(cursor_offset, line):
141170 return None
142171
143172
144- current_import_re_1 = re . compile (r'import' )
145- current_import_re_2 = re . compile (r'([\w0-9_.]+)' )
146- current_import_re_3 = re . compile (r'[,][ ]([\w0-9_.]*)' )
173+ current_import_re_1 = LazyReCompile (r'import' )
174+ current_import_re_2 = LazyReCompile (r'([\w0-9_.]+)' )
175+ current_import_re_3 = LazyReCompile (r'[,][ ]([\w0-9_.]*)' )
147176
148177def current_import (cursor_offset , line ):
149178 #TODO allow for multiple as's
@@ -161,7 +190,7 @@ def current_import(cursor_offset, line):
161190 return start , end , m .group (1 )
162191
163192
164- current_method_definition_name_re = re . compile ("def\s+([a-zA-Z_][\w]*)" )
193+ current_method_definition_name_re = LazyReCompile ("def\s+([a-zA-Z_][\w]*)" )
165194
166195def current_method_definition_name (cursor_offset , line ):
167196 """The name of a method being defined"""
@@ -172,7 +201,7 @@ def current_method_definition_name(cursor_offset, line):
172201 return None
173202
174203
175- current_single_word_re = re . compile (r"(?<![.])\b([a-zA-Z_][\w]*)" )
204+ current_single_word_re = LazyReCompile (r"(?<![.])\b([a-zA-Z_][\w]*)" )
176205
177206def current_single_word (cursor_offset , line ):
178207 """the un-dotted word just before or under the cursor"""
@@ -192,7 +221,7 @@ def current_dotted_attribute(cursor_offset, line):
192221 return start , end , word
193222
194223
195- current_string_literal_attr_re = re . compile (
224+ current_string_literal_attr_re = LazyReCompile (
196225 "('''" +
197226 r'''|"""|'|")((?:(?=([^"'\\]+|\\.|(?!\1)["']))\3)*)\1[.]([a-zA-Z_]?[\w]*)''' )
198227
0 commit comments