1
# Copyright (C) 2006 by Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Lazily compiled regex objects.
19
This module defines a class which creates proxy objects for regex compilation.
20
This allows overriding re.compile() to return lazily compiled objects.
26
_real_re_compile = re.compile
29
class LazyRegex(object):
30
"""A proxy around a real regex, which won't compiled until accessed."""
33
# These are the parameters on a real _sre.SRE_Pattern object, which we
34
# will map to local members so that we don't have the proxy overhead.
35
_regex_attributes_to_copy = [
36
'__copy__', '__deepcopy__', 'findall', 'finditer', 'match',
37
'scanner', 'search', 'split', 'sub', 'subn'
40
# We use slots to keep the overhead low. But we need a slot entry for
41
# all of the attributes we will copy
42
__slots__ = ['_real_regex', '_regex_args', '_regex_kwargs',
43
] + _regex_attributes_to_copy
45
def __init__(self, args=(), kwargs={}):
46
"""Create a new proxy object, passing in the args to pass to re.compile
48
:param args: The *args to pass to re.compile
49
:param kwargs: The **kwargs to pass to re.compile
51
self._real_regex = None
52
self._regex_args = args
53
self._regex_kwargs = kwargs
55
def _compile_and_collapse(self):
56
"""Actually compile the requested regex"""
57
self._real_regex = self._real_re_compile(*self._regex_args,
59
for attr in self._regex_attributes_to_copy:
60
setattr(self, attr, getattr(self._real_regex, attr))
62
def _real_re_compile(self, *args, **kwargs):
63
"""Thunk over to the original re.compile"""
64
return _real_re_compile(*args, **kwargs)
66
def __getattr__(self, attr):
67
"""Return a member from the proxied regex object.
69
If the regex hasn't been compiled yet, compile it
71
if self._real_regex is None:
72
self._compile_and_collapse()
73
# Once we have compiled, the only time we should come here
74
# is actually if the attribute is missing.
75
return getattr(self._real_regex, attr)
78
def lazy_compile(*args, **kwargs):
79
"""Create a proxy object which will compile the regex on demand.
81
:return: a LazyRegex proxy object.
83
return LazyRegex(args, kwargs)