bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 2052.3.4
by John Arbash Meinel [merge] bzr.dev | 1 | # Copyright (C) 2006 Canonical Ltd
 | 
| 2063.4.1
by John Arbash Meinel bzrlib.lazy_regex.lazy_compile creates a proxy object around re.compile() | 2 | #
 | 
| 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.
 | |
| 7 | #
 | |
| 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.
 | |
| 12 | #
 | |
| 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
 | |
| 16 | ||
| 17 | """Lazily compiled regex objects.
 | |
| 18 | ||
| 19 | This module defines a class which creates proxy objects for regex compilation.
 | |
| 20 | This allows overriding re.compile() to return lazily compiled objects.
 | |
| 21 | """
 | |
| 22 | ||
| 23 | import re | |
| 24 | ||
| 25 | ||
| 26 | class LazyRegex(object): | |
| 2063.4.5
by John Arbash Meinel review feedback from Martin | 27 | """A proxy around a real regex, which won't be compiled until accessed.""" | 
| 2063.4.1
by John Arbash Meinel bzrlib.lazy_regex.lazy_compile creates a proxy object around re.compile() | 28 | |
| 29 | ||
| 30 |     # These are the parameters on a real _sre.SRE_Pattern object, which we
 | |
| 31 |     # will map to local members so that we don't have the proxy overhead.
 | |
| 32 | _regex_attributes_to_copy = [ | |
| 33 | '__copy__', '__deepcopy__', 'findall', 'finditer', 'match', | |
| 34 | 'scanner', 'search', 'split', 'sub', 'subn' | |
| 35 |                  ]
 | |
| 36 | ||
| 37 |     # We use slots to keep the overhead low. But we need a slot entry for
 | |
| 38 |     # all of the attributes we will copy
 | |
| 39 | __slots__ = ['_real_regex', '_regex_args', '_regex_kwargs', | |
| 40 | ] + _regex_attributes_to_copy | |
| 41 | ||
| 42 | def __init__(self, args=(), kwargs={}): | |
| 43 | """Create a new proxy object, passing in the args to pass to re.compile | |
| 44 | ||
| 45 |         :param args: The *args to pass to re.compile
 | |
| 46 |         :param kwargs: The **kwargs to pass to re.compile
 | |
| 47 |         """
 | |
| 48 | self._real_regex = None | |
| 49 | self._regex_args = args | |
| 50 | self._regex_kwargs = kwargs | |
| 51 | ||
| 52 | def _compile_and_collapse(self): | |
| 53 | """Actually compile the requested regex""" | |
| 54 | self._real_regex = self._real_re_compile(*self._regex_args, | |
| 55 | **self._regex_kwargs) | |
| 56 | for attr in self._regex_attributes_to_copy: | |
| 57 | setattr(self, attr, getattr(self._real_regex, attr)) | |
| 58 | ||
| 59 | def _real_re_compile(self, *args, **kwargs): | |
| 60 | """Thunk over to the original re.compile""" | |
| 61 | return _real_re_compile(*args, **kwargs) | |
| 62 | ||
| 63 | def __getattr__(self, attr): | |
| 64 | """Return a member from the proxied regex object. | |
| 65 | ||
| 66 |         If the regex hasn't been compiled yet, compile it
 | |
| 67 |         """
 | |
| 68 | if self._real_regex is None: | |
| 69 | self._compile_and_collapse() | |
| 70 |         # Once we have compiled, the only time we should come here
 | |
| 71 |         # is actually if the attribute is missing.
 | |
| 72 | return getattr(self._real_regex, attr) | |
| 73 | ||
| 74 | ||
| 75 | def lazy_compile(*args, **kwargs): | |
| 76 | """Create a proxy object which will compile the regex on demand. | |
| 77 | ||
| 78 |     :return: a LazyRegex proxy object.
 | |
| 79 |     """
 | |
| 80 | return LazyRegex(args, kwargs) | |
| 81 | ||
| 2063.4.2
by John Arbash Meinel Add install and unistall functions, and tests | 82 | |
| 83 | def install_lazy_compile(): | |
| 84 | """Make lazy_compile the default compile mode for regex compilation. | |
| 85 | ||
| 86 |     This overrides re.compile with lazy_compile. To restore the original
 | |
| 87 |     functionality, call reset_compile().
 | |
| 88 |     """
 | |
| 89 | re.compile = lazy_compile | |
| 90 | ||
| 91 | ||
| 92 | def reset_compile(): | |
| 93 | """Restore the original function to re.compile(). | |
| 94 |     
 | |
| 95 |     It is safe to call reset_compile() multiple times, it will always
 | |
| 96 |     restore re.compile() to the value that existed at import time.
 | |
| 97 |     Though the first call will reset back to the original (it doesn't
 | |
| 98 |     track nesting level)
 | |
| 99 |     """
 | |
| 100 | re.compile = _real_re_compile | |
| 2063.4.5
by John Arbash Meinel review feedback from Martin | 101 | |
| 102 | ||
| 103 | _real_re_compile = re.compile | |
| 104 | assert _real_re_compile is not lazy_compile, \ | |
| 105 |     "re.compile has already been overridden as lazy_compile, but this would" \
 | |
| 106 |     " cause infinite recursion"
 |