X Tutup
Skip to content

Commit 3db074b

Browse files
committed
Lazy compile all regex
Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
1 parent e5cefc5 commit 3db074b

File tree

2 files changed

+46
-22
lines changed

2 files changed

+46
-22
lines changed

bpython/autocomplete.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import abc
2727
import keyword
2828
import os
29-
import re
3029
import rlcompleter
3130

3231
from glob import glob
@@ -461,17 +460,13 @@ def safe_eval(expr, namespace):
461460
raise EvaluationError
462461

463462

464-
attr_matches_re = None
463+
attr_matches_re = lineparts.LazyReCompile(r"(\w+(\.\w+)*)\.(\w*)")
465464

466465

467466
def attr_matches(text, namespace):
468467
"""Taken from rlcompleter.py and bent to my will.
469468
"""
470469

471-
global attr_matches_re
472-
if attr_matches_re is None:
473-
attr_matches_re = re.compile(r"(\w+(\.\w+)*)\.(\w*)")
474-
475470
# Gna, Py 2.6's rlcompleter searches for __call__ inside the
476471
# instance instead of the type, so we monkeypatch to prevent
477472
# side-effects (__getattr__/__getattribute__)

bpython/line.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,34 @@
77
from 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

1239
def 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

3158
def 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

4270
def 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+
5483
def 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

6897
def 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

87116
def 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

102131
def 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

124153
def 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

148177
def 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

166195
def 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

177206
def 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

Comments
 (0)
X Tutup