Status: | Merged |
---|---|
Approved by: | John A Meinel |
Approved revision: | no longer in the source branch. |
Merged at revision: | 143 |
Proposed branch: | lp:~jelmer/bzr-grep/lazy |
Merge into: | lp:bzr-grep |
Diff against target: |
500 lines (+242/-237) 2 files modified
__init__.py (+4/-237) cmds.py (+238/-0) |
To merge this branch: | bzr merge lp:~jelmer/bzr-grep/lazy |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John A Meinel | Approve | ||
Review via email:
|
Commit message
Description of the change
This moves the actual command implementation to a separate file.
It shaves some (limited) time off the bzr startup time.
To post a comment you must log in.
lp:~jelmer/bzr-grep/lazy
updated
- 143. By Jelmer Vernooij
-
Merge lazy loading of command implementation.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '__init__.py' |
2 | --- __init__.py 2010-06-26 02:34:08 +0000 |
3 | +++ __init__.py 2011-02-20 00:38:52 +0000 |
4 | @@ -13,249 +13,16 @@ |
5 | # You should have received a copy of the GNU General Public License |
6 | # along with this program; if not, write to the Free Software |
7 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
8 | + |
9 | """Print lines matching PATTERN for specified files and revisions.""" |
10 | |
11 | -import os |
12 | -import sys |
13 | - |
14 | -from bzrlib import errors |
15 | -from bzrlib.commands import Command, register_command, display_command |
16 | -from bzrlib.option import Option, ListOption |
17 | - |
18 | -from bzrlib.lazy_import import lazy_import |
19 | -lazy_import(globals(), """ |
20 | -import re |
21 | - |
22 | -from termcolor import allow_color |
23 | -import grep |
24 | - |
25 | -import bzrlib |
26 | -from bzrlib.revisionspec import RevisionSpec |
27 | -from bzrlib import ( |
28 | - osutils, |
29 | - bzrdir, |
30 | - trace, |
31 | - ) |
32 | -""") |
33 | +from bzrlib.commands import plugin_cmds |
34 | + |
35 | import version |
36 | |
37 | version_info = version.version_info |
38 | |
39 | -# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy |
40 | -# to avoid the error |
41 | -# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used |
42 | -# incorrectly: Object already cleaned up, did you assign it to another |
43 | -# variable?: _factory |
44 | -# with lazy import |
45 | -def _parse_levels(s): |
46 | - try: |
47 | - return int(s) |
48 | - except ValueError: |
49 | - msg = "The levels argument must be an integer." |
50 | - raise errors.BzrCommandError(msg) |
51 | - |
52 | - |
53 | -class GrepOptions(object): |
54 | - """Container to pass around grep options. |
55 | - |
56 | - This class is used as a container to pass around user option and |
57 | - some other params (like outf) to processing functions. This makes |
58 | - it easier to add more options as grep evolves. |
59 | - """ |
60 | - verbose = False |
61 | - ignore_case = False |
62 | - no_recursive = False |
63 | - from_root = False |
64 | - null = False |
65 | - levels = None |
66 | - line_number = False |
67 | - path_list = None |
68 | - revision = None |
69 | - pattern = None |
70 | - include = None |
71 | - exclude = None |
72 | - fixed_string = False |
73 | - files_with_matches = False |
74 | - files_without_match = False |
75 | - color = None |
76 | - diff = False |
77 | - |
78 | - # derived options |
79 | - recursive = None |
80 | - eol_marker = None |
81 | - patternc = None |
82 | - sub_patternc = None |
83 | - print_revno = None |
84 | - fixed_string = None |
85 | - outf = None |
86 | - show_color = False |
87 | - |
88 | - |
89 | -class cmd_grep(Command): |
90 | - """Print lines matching PATTERN for specified files and revisions. |
91 | - |
92 | - This command searches the specified files and revisions for a given |
93 | - pattern. The pattern is specified as a Python regular expressions[1]. |
94 | - |
95 | - If the file name is not specified, the revisions starting with the |
96 | - current directory are searched recursively. If the revision number is |
97 | - not specified, the working copy is searched. To search the last committed |
98 | - revision, use the '-r -1' or '-r last:1' option. |
99 | - |
100 | - Unversioned files are not searched unless explicitly specified on the |
101 | - command line. Unversioned directores are not searched. |
102 | - |
103 | - When searching a pattern, the output is shown in the 'filepath:string' |
104 | - format. If a revision is explicitly searched, the output is shown as |
105 | - 'filepath~N:string', where N is the revision number. |
106 | - |
107 | - --include and --exclude options can be used to search only (or exclude |
108 | - from search) files with base name matches the specified Unix style GLOB |
109 | - pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\ |
110 | - to quote wildcard or backslash character literally. Note that the glob |
111 | - pattern is not a regular expression. |
112 | - |
113 | - [1] http://docs.python.org/library/re.html#regular-expression-syntax |
114 | - """ |
115 | - |
116 | - encoding_type = 'replace' |
117 | - takes_args = ['pattern', 'path*'] |
118 | - takes_options = [ |
119 | - 'verbose', |
120 | - 'revision', |
121 | - Option('color', type=str, argname='when', |
122 | - help='Show match in color. WHEN is never, always or auto.'), |
123 | - Option('diff', short_name='p', |
124 | - help='Grep for pattern in changeset for each revision.'), |
125 | - ListOption('exclude', type=str, argname='glob', short_name='X', |
126 | - help="Skip files whose base name matches GLOB."), |
127 | - ListOption('include', type=str, argname='glob', short_name='I', |
128 | - help="Search only files whose base name matches GLOB."), |
129 | - Option('files-with-matches', short_name='l', |
130 | - help='Print only the name of each input file in ' |
131 | - 'which PATTERN is found.'), |
132 | - Option('files-without-match', short_name='L', |
133 | - help='Print only the name of each input file in ' |
134 | - 'which PATTERN is not found.'), |
135 | - Option('fixed-string', short_name='F', |
136 | - help='Interpret PATTERN is a single fixed string (not regex).'), |
137 | - Option('from-root', |
138 | - help='Search for pattern starting from the root of the branch. ' |
139 | - '(implies --recursive)'), |
140 | - Option('ignore-case', short_name='i', |
141 | - help='ignore case distinctions while matching.'), |
142 | - Option('levels', |
143 | - help='Number of levels to display - 0 for all, 1 for collapsed ' |
144 | - '(1 is default).', |
145 | - argname='N', |
146 | - type=_parse_levels), |
147 | - Option('line-number', short_name='n', |
148 | - help='show 1-based line number.'), |
149 | - Option('no-recursive', |
150 | - help="Don't recurse into subdirectories. (default is --recursive)"), |
151 | - Option('null', short_name='Z', |
152 | - help='Write an ASCII NUL (\\0) separator ' |
153 | - 'between output lines rather than a newline.'), |
154 | - ] |
155 | - |
156 | - |
157 | - @display_command |
158 | - def run(self, verbose=False, ignore_case=False, no_recursive=False, |
159 | - from_root=False, null=False, levels=None, line_number=False, |
160 | - path_list=None, revision=None, pattern=None, include=None, |
161 | - exclude=None, fixed_string=False, files_with_matches=False, |
162 | - files_without_match=False, color='never', diff=False): |
163 | - |
164 | - if path_list == None: |
165 | - path_list = ['.'] |
166 | - else: |
167 | - if from_root: |
168 | - raise errors.BzrCommandError('cannot specify both --from-root and PATH.') |
169 | - |
170 | - if files_with_matches and files_without_match: |
171 | - raise errors.BzrCommandError('cannot specify both ' |
172 | - '-l/--files-with-matches and -L/--files-without-matches.') |
173 | - |
174 | - if color not in ['always', 'never', 'auto']: |
175 | - raise errors.BzrCommandError('Valid values for --color are ' |
176 | - '"always", "never" or "auto".') |
177 | - |
178 | - if levels==None: |
179 | - levels=1 |
180 | - |
181 | - print_revno = False |
182 | - if revision != None or levels == 0: |
183 | - # print revision numbers as we may be showing multiple revisions |
184 | - print_revno = True |
185 | - |
186 | - eol_marker = '\n' |
187 | - if null: |
188 | - eol_marker = '\0' |
189 | - |
190 | - if not ignore_case and grep.is_fixed_string(pattern): |
191 | - # if the pattern isalnum, implicitly use to -F for faster grep |
192 | - fixed_string = True |
193 | - elif ignore_case and fixed_string: |
194 | - # GZ 2010-06-02: Fall back to regexp rather than lowercasing |
195 | - # pattern and text which will cause pain later |
196 | - fixed_string = False |
197 | - pattern = re.escape(pattern) |
198 | - |
199 | - patternc = None |
200 | - re_flags = re.MULTILINE |
201 | - if ignore_case: |
202 | - re_flags |= re.IGNORECASE |
203 | - |
204 | - if not fixed_string: |
205 | - patternc = grep.compile_pattern(pattern, re_flags) |
206 | - |
207 | - if color == 'always': |
208 | - show_color = True |
209 | - elif color == 'never': |
210 | - show_color = False |
211 | - elif color == 'auto': |
212 | - show_color = allow_color() |
213 | - |
214 | - GrepOptions.verbose = verbose |
215 | - GrepOptions.ignore_case = ignore_case |
216 | - GrepOptions.no_recursive = no_recursive |
217 | - GrepOptions.from_root = from_root |
218 | - GrepOptions.null = null |
219 | - GrepOptions.levels = levels |
220 | - GrepOptions.line_number = line_number |
221 | - GrepOptions.path_list = path_list |
222 | - GrepOptions.revision = revision |
223 | - GrepOptions.pattern = pattern |
224 | - GrepOptions.include = include |
225 | - GrepOptions.exclude = exclude |
226 | - GrepOptions.fixed_string = fixed_string |
227 | - GrepOptions.files_with_matches = files_with_matches |
228 | - GrepOptions.files_without_match = files_without_match |
229 | - GrepOptions.color = color |
230 | - GrepOptions.diff = False |
231 | - |
232 | - GrepOptions.eol_marker = eol_marker |
233 | - GrepOptions.print_revno = print_revno |
234 | - GrepOptions.patternc = patternc |
235 | - GrepOptions.recursive = not no_recursive |
236 | - GrepOptions.fixed_string = fixed_string |
237 | - GrepOptions.outf = self.outf |
238 | - GrepOptions.show_color = show_color |
239 | - |
240 | - if diff == True: |
241 | - # options not used: |
242 | - # files_with_matches, files_without_match |
243 | - # levels(?), line_number, from_root |
244 | - # include, exclude |
245 | - # These are silently ignored. |
246 | - grep.grep_diff(GrepOptions) |
247 | - elif revision == None: |
248 | - grep.workingtree_grep(GrepOptions) |
249 | - else: |
250 | - grep.versioned_grep(GrepOptions) |
251 | - |
252 | - |
253 | -register_command(cmd_grep) |
254 | +plugin_cmds.register_lazy("cmd_grep", [], "bzrlib.plugins.grep.cmds") |
255 | |
256 | def test_suite(): |
257 | from bzrlib.tests import TestUtil |
258 | |
259 | === added file 'cmds.py' |
260 | --- cmds.py 1970-01-01 00:00:00 +0000 |
261 | +++ cmds.py 2011-02-20 00:38:52 +0000 |
262 | @@ -0,0 +1,238 @@ |
263 | +# Copyright (C) 2010 Canonical Ltd |
264 | +# |
265 | +# This program is free software; you can redistribute it and/or modify |
266 | +# it under the terms of the GNU General Public License as published by |
267 | +# the Free Software Foundation; either version 2 of the License, or |
268 | +# (at your option) any later version. |
269 | +# |
270 | +# This program is distributed in the hope that it will be useful, |
271 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
272 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
273 | +# GNU General Public License for more details. |
274 | +# |
275 | +# You should have received a copy of the GNU General Public License |
276 | +# along with this program; if not, write to the Free Software |
277 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
278 | + |
279 | +"""Print lines matching PATTERN for specified files and revisions.""" |
280 | + |
281 | +from bzrlib import errors |
282 | +from bzrlib.commands import Command, display_command |
283 | +from bzrlib.option import Option, ListOption |
284 | + |
285 | +# FIXME: _parse_levels should be shared with bzrlib.builtins. this is a copy |
286 | +# to avoid the error |
287 | +# "IllegalUseOfScopeReplacer: ScopeReplacer object '_parse_levels' was used |
288 | +# incorrectly: Object already cleaned up, did you assign it to another |
289 | +# variable?: _factory |
290 | +# with lazy import |
291 | +def _parse_levels(s): |
292 | + try: |
293 | + return int(s) |
294 | + except ValueError: |
295 | + msg = "The levels argument must be an integer." |
296 | + raise errors.BzrCommandError(msg) |
297 | + |
298 | + |
299 | +class GrepOptions(object): |
300 | + """Container to pass around grep options. |
301 | + |
302 | + This class is used as a container to pass around user option and |
303 | + some other params (like outf) to processing functions. This makes |
304 | + it easier to add more options as grep evolves. |
305 | + """ |
306 | + verbose = False |
307 | + ignore_case = False |
308 | + no_recursive = False |
309 | + from_root = False |
310 | + null = False |
311 | + levels = None |
312 | + line_number = False |
313 | + path_list = None |
314 | + revision = None |
315 | + pattern = None |
316 | + include = None |
317 | + exclude = None |
318 | + fixed_string = False |
319 | + files_with_matches = False |
320 | + files_without_match = False |
321 | + color = None |
322 | + diff = False |
323 | + |
324 | + # derived options |
325 | + recursive = None |
326 | + eol_marker = None |
327 | + patternc = None |
328 | + sub_patternc = None |
329 | + print_revno = None |
330 | + fixed_string = None |
331 | + outf = None |
332 | + show_color = False |
333 | + |
334 | + |
335 | +class cmd_grep(Command): |
336 | + """Print lines matching PATTERN for specified files and revisions. |
337 | + |
338 | + This command searches the specified files and revisions for a given |
339 | + pattern. The pattern is specified as a Python regular expressions[1]. |
340 | + |
341 | + If the file name is not specified, the revisions starting with the |
342 | + current directory are searched recursively. If the revision number is |
343 | + not specified, the working copy is searched. To search the last committed |
344 | + revision, use the '-r -1' or '-r last:1' option. |
345 | + |
346 | + Unversioned files are not searched unless explicitly specified on the |
347 | + command line. Unversioned directores are not searched. |
348 | + |
349 | + When searching a pattern, the output is shown in the 'filepath:string' |
350 | + format. If a revision is explicitly searched, the output is shown as |
351 | + 'filepath~N:string', where N is the revision number. |
352 | + |
353 | + --include and --exclude options can be used to search only (or exclude |
354 | + from search) files with base name matches the specified Unix style GLOB |
355 | + pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\ |
356 | + to quote wildcard or backslash character literally. Note that the glob |
357 | + pattern is not a regular expression. |
358 | + |
359 | + [1] http://docs.python.org/library/re.html#regular-expression-syntax |
360 | + """ |
361 | + |
362 | + encoding_type = 'replace' |
363 | + takes_args = ['pattern', 'path*'] |
364 | + takes_options = [ |
365 | + 'verbose', |
366 | + 'revision', |
367 | + Option('color', type=str, argname='when', |
368 | + help='Show match in color. WHEN is never, always or auto.'), |
369 | + Option('diff', short_name='p', |
370 | + help='Grep for pattern in changeset for each revision.'), |
371 | + ListOption('exclude', type=str, argname='glob', short_name='X', |
372 | + help="Skip files whose base name matches GLOB."), |
373 | + ListOption('include', type=str, argname='glob', short_name='I', |
374 | + help="Search only files whose base name matches GLOB."), |
375 | + Option('files-with-matches', short_name='l', |
376 | + help='Print only the name of each input file in ' |
377 | + 'which PATTERN is found.'), |
378 | + Option('files-without-match', short_name='L', |
379 | + help='Print only the name of each input file in ' |
380 | + 'which PATTERN is not found.'), |
381 | + Option('fixed-string', short_name='F', |
382 | + help='Interpret PATTERN is a single fixed string (not regex).'), |
383 | + Option('from-root', |
384 | + help='Search for pattern starting from the root of the branch. ' |
385 | + '(implies --recursive)'), |
386 | + Option('ignore-case', short_name='i', |
387 | + help='ignore case distinctions while matching.'), |
388 | + Option('levels', |
389 | + help='Number of levels to display - 0 for all, 1 for collapsed ' |
390 | + '(1 is default).', |
391 | + argname='N', |
392 | + type=_parse_levels), |
393 | + Option('line-number', short_name='n', |
394 | + help='show 1-based line number.'), |
395 | + Option('no-recursive', |
396 | + help="Don't recurse into subdirectories. (default is --recursive)"), |
397 | + Option('null', short_name='Z', |
398 | + help='Write an ASCII NUL (\\0) separator ' |
399 | + 'between output lines rather than a newline.'), |
400 | + ] |
401 | + |
402 | + |
403 | + @display_command |
404 | + def run(self, verbose=False, ignore_case=False, no_recursive=False, |
405 | + from_root=False, null=False, levels=None, line_number=False, |
406 | + path_list=None, revision=None, pattern=None, include=None, |
407 | + exclude=None, fixed_string=False, files_with_matches=False, |
408 | + files_without_match=False, color='never', diff=False): |
409 | + from bzrlib.plugins.grep import ( |
410 | + grep, |
411 | + termcolor, |
412 | + ) |
413 | + import re |
414 | + if path_list == None: |
415 | + path_list = ['.'] |
416 | + else: |
417 | + if from_root: |
418 | + raise errors.BzrCommandError('cannot specify both --from-root and PATH.') |
419 | + |
420 | + if files_with_matches and files_without_match: |
421 | + raise errors.BzrCommandError('cannot specify both ' |
422 | + '-l/--files-with-matches and -L/--files-without-matches.') |
423 | + |
424 | + if color not in ['always', 'never', 'auto']: |
425 | + raise errors.BzrCommandError('Valid values for --color are ' |
426 | + '"always", "never" or "auto".') |
427 | + |
428 | + if levels==None: |
429 | + levels=1 |
430 | + |
431 | + print_revno = False |
432 | + if revision != None or levels == 0: |
433 | + # print revision numbers as we may be showing multiple revisions |
434 | + print_revno = True |
435 | + |
436 | + eol_marker = '\n' |
437 | + if null: |
438 | + eol_marker = '\0' |
439 | + |
440 | + if not ignore_case and grep.is_fixed_string(pattern): |
441 | + # if the pattern isalnum, implicitly use to -F for faster grep |
442 | + fixed_string = True |
443 | + elif ignore_case and fixed_string: |
444 | + # GZ 2010-06-02: Fall back to regexp rather than lowercasing |
445 | + # pattern and text which will cause pain later |
446 | + fixed_string = False |
447 | + pattern = re.escape(pattern) |
448 | + |
449 | + patternc = None |
450 | + re_flags = re.MULTILINE |
451 | + if ignore_case: |
452 | + re_flags |= re.IGNORECASE |
453 | + |
454 | + if not fixed_string: |
455 | + patternc = grep.compile_pattern(pattern, re_flags) |
456 | + |
457 | + if color == 'always': |
458 | + show_color = True |
459 | + elif color == 'never': |
460 | + show_color = False |
461 | + elif color == 'auto': |
462 | + show_color = termcolor.allow_color() |
463 | + |
464 | + GrepOptions.verbose = verbose |
465 | + GrepOptions.ignore_case = ignore_case |
466 | + GrepOptions.no_recursive = no_recursive |
467 | + GrepOptions.from_root = from_root |
468 | + GrepOptions.null = null |
469 | + GrepOptions.levels = levels |
470 | + GrepOptions.line_number = line_number |
471 | + GrepOptions.path_list = path_list |
472 | + GrepOptions.revision = revision |
473 | + GrepOptions.pattern = pattern |
474 | + GrepOptions.include = include |
475 | + GrepOptions.exclude = exclude |
476 | + GrepOptions.fixed_string = fixed_string |
477 | + GrepOptions.files_with_matches = files_with_matches |
478 | + GrepOptions.files_without_match = files_without_match |
479 | + GrepOptions.color = color |
480 | + GrepOptions.diff = False |
481 | + |
482 | + GrepOptions.eol_marker = eol_marker |
483 | + GrepOptions.print_revno = print_revno |
484 | + GrepOptions.patternc = patternc |
485 | + GrepOptions.recursive = not no_recursive |
486 | + GrepOptions.fixed_string = fixed_string |
487 | + GrepOptions.outf = self.outf |
488 | + GrepOptions.show_color = show_color |
489 | + |
490 | + if diff == True: |
491 | + # options not used: |
492 | + # files_with_matches, files_without_match |
493 | + # levels(?), line_number, from_root |
494 | + # include, exclude |
495 | + # These are silently ignored. |
496 | + grep.grep_diff(GrepOptions) |
497 | + elif revision == None: |
498 | + grep.workingtree_grep(GrepOptions) |
499 | + else: |
500 | + grep.versioned_grep(GrepOptions) |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 2/19/2011 6:39 PM, Jelmer Vernooij wrote: /code.launchpad .net/~jelmer/ bzr-grep/ lazy/+merge/ 50489
> Jelmer Vernooij has proposed merging lp:~jelmer/bzr-grep/lazy into lp:bzr-grep.
>
> Requested reviews:
> Bazaar Developers (bzr)
>
> For more details, see:
> https:/
>
> This moves the actual command implementation to a separate file.
>
> It shaves some (limited) time off the bzr startup time.
merge: approve
John enigmail. mozdev. org/
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAk1 mlmAACgkQJdeBCY SNAANz3wCeJ9WBF 1fIA4FO6F6XiS2M R8qm 97+dZE/ VOC0F3nj0AGSOiI n
QRcAn3zX/
=rohz
-----END PGP SIGNATURE-----